2015년 5월 7일 목요일

C/C++의 배열과 포인터

 포인터와 배열은 깊은 관계가 있는데 사실 배열의 이름이 바로 포인터이다. 다음 예를 보자.

#include <stdio.h>
int main()
{
   int iaa[] = {11,22,33,44,55};
   int ib = 4;
   printf("iaa : %p\n", iaa); //(1)
   printf("*iaa : %d\n", *iaa); //(2)
   printf("*(iaa+ib) : %d\n", *(iaa+ib)); //(3)
   printf("iaa[ib] : %d\n", iaa[ib]); //(4)
}

iaa : 0028ff08
*iaa : 11
*(iaa+ib) : 55
iaa[ib] : 55

이 예에서 (1)의 결과 를 보면 포인터(주소)값이 찍히는 것을 알 수 있으며 (2), (3), (4)의 결과를 보면 배열명은 내부적으로 배열의 첫 번째 요소의 포인터(주소)임을 알 수 있다. 그래서 배열의 첫 번째 요소를 참조하는 다음 표현식은 모두 같은 것들이다.

  • *iaa
  • *(iaa + 0)
  • iaaa[0]

마찬가지로 배열의 5번째 요소는

  • iaa[5]
  • *(iaa+5)

로 표현할 수 있다.
 또 다른 예를 보자.

#include <stdio.h>
int main()
{
   int iaa[] = {11,22,33,44,55};
int *ip = iaa;
for(int k=0; k<5; k++){
printf("iaa[%d]:%d, ", k, ip[k]);  //(1)
}
printf("\n");
for(int k=0; k<5; k++){
printf("iaa[%d]:%d, ", k, *(ip+k)); //(2)
}
printf("\n");
for(int k=0; k<5; k++){
printf("iaa[%d]:%d, ", k, *(ip++)); //(3)
}
}

iaa[0]:11, iaa[1]:22, iaa[2]:33, iaa[3]:44, iaa[4]:55,
iaa[0]:11, iaa[1]:22, iaa[2]:33, iaa[3]:44, iaa[4]:55,
iaa[0]:11, iaa[1]:22, iaa[2]:33, iaa[3]:44, iaa[4]:55,

여기서 (1)과 (2)는 완전히 같은 코드이다. 즉 ip[k] 와 *(ip+k)는 완전히 동일한 표현식이다. 하지만 (3)에서는 앞의 경우들과 달리 ip값이 직접 증가하여 변한다는 점이 다르다. 하지만 배열명에 정수를 더하거나 뺄 수 없다. 즉 iaa++, --iaa 과 같은 표현식은 에러를 발생시킨다. 배열 포인터를 직접 증감시킬 수 없으므로 다른 포인터를 하나 선언해서 거기에 배열 포인터를대입한 다음 그 포인터를 조작해야 한다.
 배열과 포인터의 차이점을 요약하면 다음과 같다.
  • 배열은 메모리가 자동으로 생성되지만 포인터는 메모리를 할당해야 한다.
  • 배열은 주소 이동이 불가능하지만 포인터는 가능하다.
  • 배열은 크기가 ‘데이터형×배열크기’ 이지만 포인터는 2 또는 4바이트이다.


댓글 없음:

댓글 쓰기