리눅스 Tips, 리눅스 C/C++ 프로그래밍, 모바일 클라우드 동향 및 테스트 등

2012년 10월 30일 화요일

리눅스 C/C++ : 10장 포인터(1)

출처 http://coolprogramming.springnote.com    저작자 NetGong


1, 포인터란

 포인터는 C언어에서 '가리킨다', '지시한다'라는 의미로 사용됩니다. 포인터는 어떤 곳의 메모리 주소를 가리킵니다. 가리킨다는 말은 메모리의 주소를 알고 있다는 말입니다. 어떤 변수나 함수 등의 주소를 가리키는 개념을 포인터라합니다. 정리하면,

  • 포인터는 주소를 저장하는 변수(메모리)를 의미합니다.(단, 그 변수가 주소를 가지고 있어야 합니다.)
  • 주소를 저장하고 있기 때문에 언제든지 그 주소의 메모리에 방문?!할 수 있고 접근할 수 있습니다.
  • 그래서 포인터는 '주소를 가리킨다'고 말하는 것입니다. '주소를 참조한다'고도 합니다.

 포인터를 만드는 방법은 간단합니다. 포인터 변수를 만들고 그 포인터 변수가 주소를 가지면 포인터(참조)가 되는 것이지요. 문법은 간단합니다.

    int     n     =   10;
    int*   pn    =  &n;

  n 은 정수를 저장하기 위한 변수(메모리공간의 이름)를 의미합니다. pn은 주소(int형주소)를 저장하기 위한 변수(메모리공간의 이름)를 의미합니다. 그리고 n에는 정수 10을 저장했습니다. pn에는 주소 &n을 저장했습니다. 그러므로 pn은 주소를 가리킵니다. 그래서 pn을 포인터라 합니다. 정리하면 앞으로 포인터와 포인터변수는 같은 용어로 사용하겠습니다. pn을 포인터라합니다.

2, 포인터의 사용


void main( )
{    int n = 10;
     int * pn = &n;
     printf("%d\n", n);
     printf("%d\n", *pn);
}
  1. 10
  2. 10

 포인터 pn은 int형 시작주소 &n(12ff60)을 저장하고 있고 pn이 int형 주소이므로 pn 앞에 * 연산자를 붙인 *pn은 n과 같은 메모리가 된다. 아래 그림은 위 예제의 간단한 메모리표현이다.


 아래는 주소를 확인하는 예제입니다.

void main( )
{    int n = 10;
     int * pn = &n;
     printf("%x\n", &n);
     printf("%x\n", pn);
}
  1. 12ff60
    12ff60

 &n과 pn 모두 12ff60입니다. 당연한 결과죠. 그러면 pn과 &n의 차이는? pn은 변수이며 &n은 주소자체(상수)이다. 변수와 주소를 참고 하세요. 위쪽 그림을 보면 포인터 pn 도 4byte 메모리 공간을 갖습니다. 모든 포인터는 4byte 크기입니다. 자세한 내용은 아래에서 다시 하도록 하겠습니다. 정리하면,

  • n은 int형 변수이며 정수를 저장한다.
  • pn은 int*형 변수이며 주소(int형주소)를 저장한다.

 char형 포인터의 예제입니다.

void main( )
{    char c = 'A';
     char * pc = &c;
     printf("%c %c\n", c, *pc);
}
  1. A A

 c는 char형 변수이며 문자 'A' (정수 65)를 저장합니다. 'A'가 정수 65인지 다음에 설명합니다.
pc는 char*형 변수이며 시작주소 &c(주소 12ff60)를 저장합니다. *pc는 pc의 주소 메모리인 c 입니다. 아래 그림을 참고 하세요.


 포인터 변수 pc도  4byte 메모리 공간을 사용합니다. 모든 포인터 변수의 크기는 4byte입니다.
또 한가지 발견하셨나요?  int형 변수 주소는 int형 포인터에 char형 변수 주소는 char형 포인터에 저장해야 합니다. 이유는 다음에 설명하겠습니다. 지금은 무조건 같은 자료형에 저장해야 한다는 것만 알아 두세요.

 여기까지 잘 오셨습니다. 이제 여러분은 포인터가 무엇인지 어떻게 사용하는 지 확실히 알았습니다. 하지만 어디에 왜? 사용하는지는? 공부하지 않았습니다. 곧 공부하게 됩니다. 조금 기다리세요.

3, 포인터의 크기

 모든 포인터의 크기는 4byte라고 했죠? 그래서 준비했습니다. 확인을 해보도록 하죠. (단, 우리는 다른 언급이 없으면 32bit OS를 기준으로 설명한다고 했습니다. 그래서 포인터의 크기가 모두 4byte입니다. 만약 64bit OS라면 포인터의 크기는 64bit가 됩니다.)

 자 연산자 하나를 더 배우도록 하겠습니다. 연산자 sizeof()입니다. 이 연산자는 함수와 비슷하게 동작하는 연산자입니다. 이 연산자는 변수, 자료형등의 byte수를 구할 때 사용합니다.

void main( )
{    printf("%d\n", sizeof( char ) );
     printf("%d\n", sizeof( int ) );
     printf("%d\n", sizeof( double ) );
}
  1. 1
  2. 4
  3. 8

 간단하게 자료형의 크기를 구할 수 있습니다.

void main( )
{    char c=0;
     int n=0;
     double d=0;
     printf("%d\n", sizeof( c ) );
     printf("%d\n", sizeof( n ) );
     printf("%d\n", sizeof( d ) );
}
  1. 1
  2. 4
  3. 8

 변수의 크기는 당연히 자료형의 크기와 같습니다.

void main( )
{    printf("%d\n", sizeof( char* ) );
     printf("%d\n", sizeof( int* ) );
     printf("%d\n", sizeof( double* ) );
}
  1. 4
  2. 4
  3. 4
 포인터의 크기는 모두 4byte입니다.

void main( )
{    char* pc=0;
     int* pn=0;
     double* pd=0;
     printf("%d\n", sizeof( pc ) );
     printf("%d\n", sizeof( pn ) );
     printf("%d\n", sizeof( pd ) );
}
  1. 4
  2. 4
  3. 4
포인터 변수의 크기도 모두 4byte입니다.

 자 그럼 포인터의 크기는 왜? 4byte일까요? 32bit OS에서 주소의 크기는 4byte를 넘지 않기 때문입니다. 포인터란 주소를 저장하는 변수고 주소가 4byte를 넘지 않기 때문에 4byte이면 모든 어떤 주소든 저장이 가능하겠죠. 그래서 포인터는 모두 4byte의 크기를 갖는 겁니다. 아셨죠?

오늘은 여기까지... 수고 하셨습니다.
오늘은 반복을 강조하고 싶네요. 반복학습은 이해와 암기에 정말 효과적인 학습 방법입니다.

댓글 1개:

  1. 추가적인 사항 :
    - 포인터에 대해서 가르칠 때의 방법 제안(http://kldp.org/node/104573)
    - 포인터의 포인터를 인수로 넘겨주는 이유(http://kldp.org/node/98933#comment-461949)

    답글삭제