31.0 포인터 사용하기

지금까지 우리는 값을 저장할 때 변수를 사용했습니다. 그럼 변수는 어디에 생기는 것일까요?

int num1 = 10;

다음과 같이 변수는 컴퓨터의 메모리에 생성됩니다. 즉, 메모리에 일정한 공간을 확보해두고 원하는 값을 저장하거나 가져오는 방식입니다.

그림 31-1 메모리와 변수

보통 변수는 num1과 같이 이름으로 사용하지만 메모리의 특정 장소에 위치하고 있으므로 메모리 주소로도 표현할 수 있습니다. 일상 생활에서 집을 구분할 때 주소를 사용하는 것과 같은 원리입니다.

그럼 변수의 메모리 주소를 구해보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

  • &변수

address.c

#include <stdio.h>

int main()
{
    int num1 = 10;

    printf("%p\n", &num1);    // 008AF7FC: num1의 메모리 주소를 출력
                              // 컴퓨터마다, 실행할 때마다 달라짐

    return 0;
}

실행 결과

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

변수의 메모리 주소를 구할 때는 변수 앞에 & (주소 연산자)를 붙이면 됩니다. 여기서는 &num1과 같이 num1 앞에 &를 붙여서 변수 num1의 메모리 주소를 구했습니다.

메모리 주소는 008AF7FC과 같이 16진수 형태이며 printf에서 서식 지정자 %p를 사용하여 출력합니다(pointer의 약어로 p를 사용). 물론 16진수로 출력하는 %x, %X를 사용해도 됩니다. 이때 메모리 주소는 고정된 것이 아니라 컴퓨터마다, 실행할 때마다 달라집니다.

그림 31-2 변수의 메모리 주소
참고 | 32비트, 64비트와 메모리 주소

다음과 같이 시스템이 32비트인지 64비트인지에 따라 메모리 주소의 범위도 달라집니다.

  • 32비트: 16진수 8자리
    • 0x00000000 ~ 0xFFFFFFFF
    • 예) 0x008AF7FC
  • 64비트: 16진수 16자리
    • 0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
    • 예) 0x00000000008AF7FC
    • 64비트 메모리 주소는 0x00000000`00000000처럼 8자리씩 끊어서 `를 붙이기도 합니다.

앞으로 16진수 8자리 또는 16자리로 된 숫자가 나오면 일단 메모리 주소라 생각하면 됩니다. 이제 16진수 표기는 두려워하지 마세요.

참고 | 리눅스, macOS에서 %p

리눅스, macOS에서 서식 지정자 %p를 사용하면 메모리 주소 008AF7FC0x8af7fc와 같이 앞에 0x가 붙고, A~F는 소문자로 출력됩니다. 또한, 높은 자릿수의 0은 생략됩니다.

이제부터 메모리 주소를 다루는 포인터에 대해 알아보겠습니다. 포인터는 C 언어를 배울 때 가장 큰 난관으로 알려져 있습니다. 이 책에서는 포인터를 쉽게 설명하고자 신경을 썼지만 아무래도 초보자들에게는 조금 어려운 것이 사실입니다. 이해가 되지 않는다고 걱정하지 않아도 됩니다. 다른 사람들도 다 어려워하니까요.