..

Search

30) 포인터와 배열의 관계

30) 포인터와 배열의 관계

포인터와 배열의 관계


포인터와 배열의 관계

포인터와 배열은 매우 긴밀한 관계를 맺고 있으며, 어떤 부분에서는 서로를 대체할 수도 있습니다.

 

배열의 이름은 그 값을 변경할 수 없는 상수라는 점을 제외하면 포인터와 같습니다.

따라서 배열의 이름은 포인터 상수(constant pointer)입니다.

 

포인터 상수(constant pointer)란 포인터 변수가 가리키고 있는 주소 값을 변경할 수 없는 포인터를 의미하며,
상수 포인터(pointer to constant)란 상수를 가르키는 포인터를 의미합니다.

 

예제

int arr[3] = {10, 20, 30}; // 배열 선언

int* ptr_arr = arr;        // 포인터에 배열의 이름을 대입함  

 

printf("배열의 이름을 이용하여 배열 요소에 접근 : %d %d %d\n", arr[0], arr[1], arr[2]);

printf("     포인터를 이용하여 배열 요소에 접근 : %d %d %d\n", ptr_arr[0], ptr_arr[1], ptr_arr[2]);  

printf("배열의 이름을 이용한 배열의 크기 계산 : %d\n", sizeof(arr));

printf("     포인터를 이용한 배열의 크기 계산 : %d\n", sizeof(ptr_arr));  

코딩연습 ▶

실행 결과

배열의 이름을 이용하여 배열 요소에 접근 : 10 20 30

     포인터를 이용하여 배열 요소에 접근 : 10 20 30

배열의 이름을 이용한 배열의 크기 계산 : 12

     포인터를 이용한 배열의 크기 계산 : 8

 

위의 예제에서는 포인터에 배열의 이름을 대입한 후, 해당 포인터를 배열의 이름처럼 사용합니다.

이처럼 C언어에서는 배열의 이름을 포인터처럼 사용할 수 있을 뿐만 아니라, 포인터를 배열의 이름처럼 사용할 수도 있습니다.

 

하지만 배열의 크기를 계산할 때에는 배열의 이름과 포인터 사이에 차이가 발생합니다.

배열의 이름을 이용한 크기 계산에서는 배열의 크기가 int형 배열 요소 3개의 크기인 12바이트로 제대로 출력됩니다.

하지만 포인터를 이용한 크기 계산에서는 배열의 크기가 아닌 포인터 변수 자체의 크기가 출력되는 차이가 있습니다.


배열의 포인터 연산

다음 예제는 앞선 예제와는 반대로 배열의 이름을 포인터처럼 사용하는 예제입니다.

배열의 이름으로 포인터 연산을 수행하여 각각의 배열 요소에 접근합니다.

예제

int arr[3] = {10, 20, 30}; // 배열 선언  

printf("          배열의 이름을 이용하여 배열 요소에 접근 : %d %d %d\n", arr[0], arr[1], arr[2]);

printf("배열의 이름으로 포인터 연산을 해 배열 요소에 접근 : %d %d %d\n", *(arr+0), *(arr+1), *(arr+2));

코딩연습 ▶

실행 결과

          배열의 이름을 이용하여 배열 요소에 접근 : 10 20 30

배열의 이름으로 포인터 연산을 해 배열 요소에 접근 : 10 20 30

 

배열 이름

 

따라서 배열의 이름과 포인터 사이에는 다음과 같은 공식이 성립함을 알 수 있습니다.

공식

arr이 배열의 이름이거나 포인터이고 n이 정수일 때,

arr[n] == *(arr + n)

 

위의 공식은 1차원 배열뿐만 아니라 다차원 배열에서도 언제나 성립합니다.

 

배열에 관계된 연산을 할 때는 언제나 배열의 크기를 넘어서는 접근을 하지 않도록 주의해야 합니다.

포인터 연산을 이용하여 계산하다가 배열의 크기를 넘어서는 접근을 하는 경우, C 컴파일러는 어떠한 오류도 발생시키지 않습니다.

다만 잘못된 결과만을 반환하므로 C언어로 프로그래밍할 때에는 언제나 배열의 크기에도 주의해야 합니다.


연습문제