전 포스팅에서는 포인터에 변수의 주소를 저장하는 방법을 알아보았다.

포인터는 변수의 주소를 저장하는 역할만이 아닌 포인터를 통해 값을 읽어오거나 변경할 수 있다.

포인터p가 가르키는 주소에 저장된 내용을 읽으려면 *p를 하면 된다

이것을 포인터(주소)를 통해 메모리를 간접참조 한다고 한다.

아래 예제를 보자

#include <stdio.h>
int main() {
	int i = 3000;
	int *p = NULL;
	p = &i; //주소를 p에 대입
	printf("%u\n", p);
	printf("%u\n", &i);
	printf("%d\n", i);
	printf("%d\n", *p);
}

실행 해보았는가? p와 &i는 같고 i와 *p가 같다.

즉 *를 사용하여 주소의 메모리를 참조 할 수 있다. 참조하는 크기는 선언된 포인터의 자료형으로 계산된다.

포인터의 연산은 포인터의 자료형에 따라 결과가 달라진다

#include<stdio.h>
int main() {
	char *pc;
	int *pi;
	double *pd;

	pc = (char *)10000; //주소를 10000으로 초기화
	pi = (int *)10000;
	pd = (double *)10000;
	printf("증가 전 char %d	int %d	double %d\n", pc, pi, pd);
	pc++; //1씩 올린다
	pi++;
	pd++;
	printf("증가 후 char %d	int %d	double %d\n", pc, pi, pd);
}

증가 후 각 포인터의 값은 1의 상승이 아닌 각 자료형의 크기만큼 올라간다.

즉 포인터 변수의 계산은 자료형에 따라 달라진다.

아래 예제를 통해 포인터 변수 참조와 포인터 연산에 대해 알아보자

#include<stdio.h>
int main() {
	int i = 10;
	int *pi = &i; //이는 int *p; p=&i와 같다. *p=&i가 아니다
	printf("i = %d, pi = %u\n", i, *pi);
	(*pi)++; //pi의 주소를 참조한 값은 1 올린다
	printf("i = %d, *pi = %u\n\n", i, *pi);
	*pi++; //참조하기전 pi의 값을 올린다
	printf("i = %d, *pi = %u\n\n", i, *pi); //*pi보다 4 큰 메모리의 주소에 있는 데이터이다
}

위의 예제에서 알아야 하는 것은 *가 어디에 있느냐에 따라 결과가 달라진다.

*pi는 pi에 저장된 주소의 데이터를 참조한다. 중요한것은 *(pi)++를 해야지 pi의 주소를 참조한 후 ++가 진행되지 *pi++를 하면 ++가 진행된 후 *(참조)가 진행된다

즉 참조할 메모리의 값을 바꾸는 것이 아닌 메모리를 참조하는 값을 바꾸려는 것이라면

*를 사용해 먼저 불러온 후 이후 계산을 해야한다.

#include<stdio.h>
int main() {
	int data = 0x1A2B3C4D; //16진수 0x0A0B0C0D
	printf(" %x\n", data);
	char *pc;
	pc = (char *)&data; //&data를 char로 참조
	for (int i = 0; i < 4; i++)
	{
		printf(" %x\n", *(pc + i));
	}
}

즉 int data로 4까지의 주소를 char형으로 1로 나누게 되어

0A0B0C0D가 저장된 메모리를 4개로 나누게 된다.

나눠진 결과로는 4d 3c 2b 1a로 메모리의 주소가 1씩 올라가며 메모리를 참조한다.

왜 역순으로 저장되는것인지는 모르겠으나 int형 4바이트를 char형 1바이트로 형변환 후 하나씩 출력했다는 사실을 알 수 있다.

카테고리:

업데이트: