31.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 포인터라고도 부릅니다).
즉, 다음과 같이 포인터는 메모리의 특정 위치를 가리킬 때 사용합니다(포인터는 프레젠테이션에서 사용하는 레이저 포인터의 그 포인터입니다. 어떤 위치를 콕 찝어서 가르키는 역할이죠).
이제 다음 코드를 그림으로 표현해보겠습니다.
int *numPtr; // 포인터 변수 선언 int num1 = 10; numPtr = &num1; // num1의 메모리 주소를 포인터 변수에 저장
numPtr은 10이 저장된 메모리 공간을 가리킵니다. 즉, 변수 num1이 있는 공간을 가리키게 되는 것이죠.
다음과 같이 시스템이 32비트인지 64비트인지에 따라 포인터의 크기가 달라집니다.
- 32비트: 16진수 8자리
- 0x00000000 ~ 0xFFFFFFFF
- 64비트: 16진수 16자리
- 0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
sizeof로 포인터의 크기를 구해보면 32비트에서는 4바이트, 64비트에서는 8바이트가 나옵니다.
- sizeof(포인터)
- sizeof(자료형 *)
32비트
int *numPtr; printf("%d\n", sizeof(numPtr)); // 4: 32비트에서 int 포인터는 4바이트 printf("%d\n", sizeof(char *)); // 4: 32비트에서 char 포인터는 4바이트
64비트
int *numPtr; printf("%d\n", sizeof(numPtr)); // 8: 64비트에서 int 포인터는 8바이트 printf("%d\n", sizeof(char *)); // 8: 64비트에서 char 포인터는 8바이트