본문 바로가기

윤성우의 C Programming

Chapter 12. 포인터의 이해

주소 값의 저장을 목적으로 선언되는 포인터 변수 

변수가 선언되면, 메모리 공간에 다음과 같이 할당된다. 

int main(void)

{
char letter1='A';  //char는 1바이트 
char letter2='B';

int num = 10; // int는 4바이트

...
}

C언어에서는 시작 번지만을 가지고 위치를 표현한다. 따라서 정수 10인 공간의 위치를 표현할 때는 이렇게 말한다. 

 

"정수 10은 0x12ff72 번지에 할당되어 있다. " 

 

그런데 주소 값 0x12ff72 역시 정수이기 때문에 이것도 저장이 가능한 값이며, 이의 저장을 위해 마련된 변수가 '포인터 변수' 이다. 즉 포인터 변수란 메모리의 주소 값을 저장하기 위한 변수이다. 

 

참고로 예시의 메모리 블록 주소 값은 8자리로 이루어져있는데 이는 64비트 시스템이기 때문이다. 32비트면 4자리, 16비트면 2자리이다. 

포인터 변수와 &연산자

포인터 변수는 어떤 지역을 찾아가기 위해 집 주소를 기록해둔 주소록이라면, &연산자는 집이나 건물의 실제 위치를 알려주는 우편 주소와 같다. 포인터 변수가 메모리 상의 어떤 '위치'를 저장하면, &연산자가 마치 집이나 건물의 실제 위치를 알려주는 우편 주소처럼, 변수가 컴퓨터 메모리 내의 어디에 위치해 있는지 알려주는 주소를 제공한다.

#include <stdio.h>

int main() {
    int houseNumber = 123; // 'houseNumber' 변수는 집의 번호를 저장하고 있다.
    int *addressBook; // 'addressBook' 포인터 변수는 주소록으로, 주소를 저장한다.

    addressBook = &houseNumber; // &연산자를 사용하여 'houseNumber'의 주소를 'addressBook'에 저장한다.
...
}

잘못된 포인터의 사용 

포인터는 메모리 공간에 접근이 가능하기 때문에 잘못된 포인터 사용과 관련해서는 상당히 주의를 해야 한다. 다음은 포인터가 잘못 사용된 예이다. 

Case 1 : 포인터 변수를 선언하지 않고 초기화하지 않는 경우 

int main(void)
{
int * ptr; // 포인터 변수를 초기화하지 않아서 쓰레기 값이 들어간다. 
*ptr = 100;
}

 

Case 2: 포인터 변수를 알 수 없는 값으로 초기화하는 경우 

포인터 변수를 100으로 초기화했지만 100번지가 어디에 있는지 알 수 없기 때문에 쓰레기 값으로 초기화하는 것과 동일한 결과를 낳는다. 

int main(void)
{
int * ptr = 100; // 100번지가 어디에 있음??
*ptr += 30 ;
}

포인터 초기화의 올바른 사용 예시

포인터 변수는 0으로 초기화해야 한다. 이를 널 포인터라고 한다. 이는 0번지를 의미하는 것이 아니라 아무 곳도 가리키지 않는다는 의미를 가지고 있다. 

int main(void)
{
int *ptr = 0; 
int * ptr = NULL; // NULL과 0은 같은 뜻임
...
}