2015년 5월 6일 수요일

C/C++언어의 포인터(pointer) 선언

 포인터(pointer)는 무엇인가를 가리키고 있는 것이라는 뜻인데 C/C++언어에서 포인터는 ‘메모리 주소(memory address)’이다. 변수를 선언하면 메모리 공간 어디엔가 그 변수값을 저장하기 위한 기억 공간이 할당되는데 포인터는 그 메모리 공간의 주소값을 가진다. 즉 변수값이 존재하는 물리적인 위치 정보인 것이다.
 포인터를 사용하는 경우는 여러 가지가 있다. 보통은 어떤 함수 내부에서 다른 함수의 변수값을 직접 변경시켜야 될 경우에 사용될 수 있다. 변수값이 아니라 주소값을 인자로 넘겨서 그 주소에 저장된 데이터를 직접 변경시키는 것이다. 또는 복잡한 구조를 가지는 배열이나 구조체가 함수의 인자로 사용될 경우 데이터형을 전달하기도 힘들뿐더러 메모리 낭비 및 비효율성으로 인한 속도 저하를 가져올 수 있다.
 포인터의 다양한 쓰임새 때문에 C/C++언어에는 관련된 많은 기능을 제공하고 있지만 편리한 만큼 위험부담도 있다. 경우에 따라서 매우 잡기 힘든 버그를 생산하기도 하고 심지어 시스템이 다운이 되어버리는 경우도 포인터 때문에 발생하기도 한다. 따라서 사용자는 사용법을 정확히 알고 주의해서 사용해야 한다.

 포인터의 선언은 다음과 같이 한다.

   데이터형 *포인터변수명;

기본 데이터형의 선언 방식에서 데이터 형과 변수명 사이에 별표(*)가 추가되었음을 알 수 있다. 이 문자가 추가됨으로서 뒤의 변수는 ‘포인터(주소)’가 된다. 예를 들어서 int형 포인터는 다음과 같이 선언한다.

   int *ip;

여기서 ip는 int형 포인터(주소)로 선언된 것이다. 이 포인터변수는 아직 초기화되지 않았다. int형 포인터의 초기화는  int형 변수의 주소를 대입하면 된다.

   int ia=1, *ip;
   ip = &ia;

여기서 두 번째 줄에선 ip포인터가 변수 ia의 주소값으로 초기화 되었다. &ia 는 ‘변수 ia의 주소값’이다. &는 변수의 주소를 구해주는 연산자이다.

 포인터도 다음과 같이 선언과 동시에 초기화를 할 수 있다.

   int ia=1;
   int *ip = &ia;

 계속 언급하는 바와 같이 포인터가 가리키는 것은 변수의 주소이다. 만일 가리키는 변수의 값을 읽어오거나 수정할 경우에는 포인터형 변수 앞에 ‘*’를 붙이면 된다.

   int ia = 1;
   int *ip = &ia; // (1)
   *ip = 2; // (2)
   printf(“ia=%d, *ip=%d”, ia, *ip); //(3)

이 예에서 (1)에서는 int형 포인터 ip를 선언하고 동시에 ia의 주소로 초기화하였다. 그리고 (2)에서 ip의 주소에 저장된 (int형) 데이터를 2로 수정하였다. 그렇다면 변수 ia도 같이 변하는 효과가 있는 것이다. 이와 같이 포인터에 저장된 데이터를 수정하려면 포인터 앞에 별표(*)를 같이 써주면 된다. 즉 *ip 는 변수 a와 완전히 동일하게 사용할 수 있다.

  • ip 는 &ia 와 같다.
  • *ip는 ia와 같다.

 한 가지 혼동하기 쉬운 것은 포인터 선언에서 쓰이는 별표(*)와 나중에 포인터에 붙여서 쓰는 별표(*)의 의미가 다르다는 것이다.

   int ia = 1, ib = 2;
   int *ipa = &ia;
   int *ipb = ipa;
   *ipb = ib;

이 예제와 같이 선언/초기화하였다면 ia와 *ipa, *ipb 는 동일한 변수와 같이 사용된다. 즉 *ipa 가 변하면 ia도 변경되고 *ipb가 변경되도 마찬가지로 ia도 수정된다.


댓글 없음:

댓글 쓰기