포인터

1 minute read


변수의 주소

선언된 변수들은 메모리 공간에 저장되며 이 저장된 공간을 접근하기 위한 값으로 메모리 주소가 할당된다.

이런 주소를 저장하는 변수를 포인터라고 한다. 포인터를 사용하는 이유는 배열처럼 주소가 연속적인 경우나 동적 할당된 메모리 영역에 접근과 조작이 용이하다.

포인터는 메모리 공간을 효율적으로 사용할 수 있다는 극도의 장점이 있지만 그만큼 사용자가 신경써서 제어해야 한다는 단점도 있다.


포인터의 주소 저장

포인터는 뜻 그대로 무엇을 가리킨다는 것으로 컴퓨터에서는 대상의 주소를 가리키게된다.

#include <stdio.h>

int main()
{
  int a = 0;
  int* pa = &a;

  printf("%X", &a);
  printf("%X", pa);
  printf("%X", &pa);
  printf("%d", *pa);

  return 0;
}

&는 주소 연산자로 변수의 메모리 주소를 참조한다.

코드를 실행 해보면 동일한 값이 나오는걸 확인할 수 있다. 메모리주소는 16진수로 표현되기 때문에 %X 포맷을 사용했지만 주소를 출력해주는 포맷인 %p가 따로 있기 때문에 주소를 출력해볼 때는 %p를 사용하는게 좋다. (00x0 형식으로 표현)

포인터 또한 별도로 자신의 주소를 가지고 있기 때문에 이중 삼중 … 다중으로 포인터를 사용할 수 있게된다.

*pa의 출력결과를 보면 pa에 저장된 주소를 참조해서 그 주소에 저장된 정수값인 0이 출력된다.


배열과 포인터

이 시점에서 배열을 다시 살펴본다.

int a[10] = { 0 };

a라는 변수는 a[0]의 주소값 즉, 배열의 시작주소를 가지고 있다.

a = &a[0]

이 a에 저장된 주소를 참조하면 a[0]의 값을 알 수 가 있으므로 *a는 a[0]의 값을 나타낸다고 볼 수 있다. 그렇다면 *(a + 0)이 a[0]으로 볼 때 *(a + 1) = a[1] 도 성립이 가능한가?

코드를 통해 직접확인해 본다.

int a[5] = { 1, 2, 3, 4, 5 };

for (int i = 0; i < 5; i++)
{
	printf("%d\n", *(a + i));
}

1 2 3 4 5가 한줄에 하나씩 출력되는 결과가 나온다.
배열에서 다음 주소와의 간격은 그 배열의 자료형 크기이다. 즉, 포인터의 +1은 그것이 참조하고 있는 자료형의 크기만큼 주소를 더한다는걸 알 수 있다.

Tags: ,

Categories:

Updated: