글에 들어가기에 앞서, 이 글을 요약하면 다음과 같습니다.

해당 글은 포인터를 사용하는 방법보다는, 포인터가 무엇을 저장하고 어떻게 작동하는 지에 대해서 중점적으로 설명하는 글입니다. 때문에 C에 대한 기초적인 지식과 일부 컴퓨터의 작동원리에 대한 이해가 필요합니다.

포인터의 개념

포인터도 변수다

포인터를 이해하기에 앞서, 포인터가 담고 있는 값에 대해서 이해를 해야한다. 사실 이를 이해하면 포인터를 모두 이해한 것이나 다름없다. 정말 간단하게 한 줄로 표현할 수 있다.

"포인터는 메모리의 주소를 담는 변수이다"

포인터는 단순히 메모리의 주소를 담는 변수이다. int * int ** 심지어 vector<int> ******도 마찬가지이다. 포인터 변수 속에는 결국 어떤 메모리의 주소가 담겨있다. 심지어, 메모리 주소값은 크기가 동일하기 때문에 vector<int> ******와 int * void * 의 자료형 크기도 동일하다.

/* 포인터 자료형의 크기는 얼마일까? */
#include <stdio.h>
int main(void)
{
	printf("sizeof int * %ld\\n", sizeof(int *));
	printf("sizeof void * %ld\\n", sizeof(void *));
	printf("sizeof char * %ld\\n", sizeof(char *));
	printf("sizeof int ****** %ld\\n", sizeof(int ******));
	return (0);
}
sizeof int * 8
sizeof void * 8
sizeof char * 8
sizeof int ****** 8

이제 포인터가 무슨 값을 담는지 이해했다. 그런데 다시 또 다른 난관에 부딪힌다. '그러면 타입은 왜 다른건데?'

포인터 자료형

포인터 변수도 여러가지 타입이 있다. 단순히 메모리 주소를 저장하는 변수라면서 왜 자료형을 명시하는걸까? 이를 이해하기 위해서는 자료형을 붙인 포인터들이 어떤 행동을 할 수 있는지 이해해야한다. 아래 코드를 보면서 이해해보자.

모든 포인터는 모든 메모리 주소를 담을 수 있다.

#include <stdio.h>
int main(void)
{
	char		charValue = 'a';
	int			intValue = 1;
	long long	longValue = 2;
	char		*charPValue = &intValue;
	int			*intPValue = &charValue;
	long long	*longPValue = &charPValue;
	char		**charPPValue = &longValue;

	printf("charP is %X original address is %X\\n", charPValue, &intValue);
	printf("intP is %X original address is %X\\n", intPValue, &charValue);
	printf("longP is %X original address is %X\\n", longPValue, &charPValue);
	printf("charPP is %X original address is %X\\n", charPPValue, &longValue);

	return (0);
}
charP is 6EE6F564 original address is 6EE6F564
intP is 6EE6F56B original address is 6EE6F56B
longP is 6EE6F550 original address is 6EE6F550
charPP is 6EE6F558 original address is 6EE6F558