34.1 포인터 변수 선언하기

변수의 메모리 주소를 구해보았는데 메모리 주소는 어디에 저장해야 할까요? C 언어에서 메모리 주소는 포인터(pointer) 변수에 저장합니다.

다음과 같이 포인터 변수는 *를 사용하여 선언합니다(포인터 변수는 포인터로 줄여서 부르기도 합니다).

  • 자료형 *포인터이름;
  • 포인터 = &변수;

pointer.c

#include <stdio.h>

int main()
{
    int *numPtr;      // 포인터 변수 선언
    int num1 = 10;    // int형 변수를 선언하고 10 저장

    numPtr = &num1;   // num1의 메모리 주소를 포인터 변수에 저장

    printf("%p\n", numPtr);    // 0055FC24: 포인터 변수 numPtr의 값 출력
                               // 컴퓨터마다, 실행할 때마다 달라짐
    printf("%p\n", &num1);     // 0055FC24: 변수 num1의 메모리 주소 출력
                               // 컴퓨터마다, 실행할 때마다 달라짐

    return 0;
}

실행 결과

0055FC24 (메모리 주소. 컴퓨터마다, 실행할 때마다 달라짐)
0055FC24 (메모리 주소. 컴퓨터마다, 실행할 때마다 달라짐)

포인터 변수를 선언할 때는 자료형 뒤에 * (Asterisk, 애스터리스크)를 붙입니다. *의 위치에 따른 차이는 없으며 모두 같은 뜻입니다.

int* numPtr;     // 자료형 쪽에 *을 붙임
int * numPtr;    // 자료형과 변수 가운데 *를 넣음
int *numPtr;     // 변수 쪽에 *을 붙임

포인터 변수를 선언했으면 다음과 같이 &로 변수의 주소를 구해서 포인터 변수에 저장합니다.

numPtr = &num1;   // num1의 메모리 주소를 포인터 변수에 저장

이제 printf로 포인터 numPtr의 값을 출력해보면 변수 num1의 메모리 주소가 나옵니다. 즉, 포인터와 메모리 주소는 같은 의미입니다.

printf("%p\n", numPtr);    // 0055FC24: 포인터 변수 numPtr의 값 출력
                           // 컴퓨터마다, 실행할 때마다 달라짐
printf("%p\n", &num1);     // 0055FC24: 변수 num1의 메모리 주소 출력
                           // 컴퓨터마다, 실행할 때마다 달라짐

포인터 변수를 선언할 때는 자료형을 알려주고 *를 붙이는 방식을 사용합니다. 만약 변수가 int형이면 이 변수의 메모리 주소를 저장하는 포인터는 int *라야 합니다.

여기서 int *는 영어로 pointer to int라고 읽는데 int형 공간을 가리키는 포인터라는 뜻입니다(간단하게 int 포인터라고도 부릅니다).

그림 34-3 int 포인터

즉, 다음과 같이 포인터는 메모리의 특정 위치를 가리킬 때 사용합니다(포인터는 프레젠테이션에서 사용하는 레이저 포인터의 그 포인터입니다. 어떤 위치를 콕 찝어서 가르키는 역할이죠).

그림 34-4 포인터와 메모리

이제 다음 코드를 그림으로 표현해보겠습니다.

int *numPtr;     // 포인터 변수 선언
int num1 = 10;

numPtr = &num1;   // num1의 메모리 주소를 포인터 변수에 저장

numPtr은 10이 저장된 메모리 공간을 가리킵니다. 즉, 변수 num1이 있는 공간을 가리키게 되는 것이죠.

그림 34-5 포인터에 변수의 메모리 주소 할당
참고 | 32비트와 64비트와 포인터 크기

다음과 같이 시스템이 32비트인지 64비트인지에 따라 포인터의 크기가 달라집니다.

  • 32비트: 16진수 8자리
    • 0x00000000 ~ 0xFFFFFFFF
  • 64비트: 16진수 16자리
    • 0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF

sizeof로 포인터의 크기를 구해보면 32비트에서는 4바이트, 64비트에서는 8바이트가 나옵니다.

  • sizeof(포인터)
  • sizeof(자료형 *)

32비트

int *numPtr;
printf("%u\n", sizeof(numPtr));    // 4: 32비트에서 int 포인터는 4바이트

printf("%u\n", sizeof(char *));    // 4: 32비트에서 char 포인터는 4바이트

64비트

int *numPtr;
printf("%lu\n", sizeof(numPtr));    // 8: 64비트에서 int 포인터는 8바이트

printf("%lu\n", sizeof(char *));    // 8: 64비트에서 char 포인터는 8바이트

64비트로 컴파일하는 방법은 '부록 13. 64비트 사용하기'을 참조하세요.