。공부 。

[C언어] 2차원 배열의 포인터 타입

kyoe 2008. 1. 23. 00:22
1차원 배열의 포인터 타입을 결정할때 우리는 포인터의 자료형과 포인터 연산시 증가하는 바이트 크기가 같다 는것을 알고 있다.
그럼 2차원 배열은 어떨까? 1차원 배열과 같을까? 이렇게 같으면 얼마나 좋으련만.. 그렇지가 않다.
포인터의 자료형은 1차원배열과 마찬가지로 포인터가 가르키는 자료형과 일치하지만 포인터 연산시 증가하는 바이트의 크기가 틀리다. 같은 int형 배열이더라도 증가하는 값은 4byte로 동일한것이아니라 그때 그때 틀리다는 것이다.

예를 들어 보자.
int arr[3][2] = {1,2,3,4,5,6};
위와같이 3*2배열이 있다.
자료형은 당연히 int형일테지만 포인터 연산시 증가하는 값은 몇byte일까?
확인하는 간단한 방법은 주소값을 출력하면 되겠죠
printf("arr[0] : %d\n",arr[0]);
printf("arr[1] : %d\n",arr[1]);
printf("arr[2] : %d\n",arr[2]);
2차원 배열에서 arr[0] 이라 함은 배열의특정 위치를 가르키는 포인터가 된다 즉 주소값을 갖게된다.
하지만 arr[0][0] 은 배열의 요소값을 가르키기때문에 출력하면 1값이 출력될것이다.
이렇게 주소를 출력하면 이런값이 뜬다 결과값이 개개인 컴퓨터마다 틀리겠지만 증가값은 같다.
arr[0] : 0x00
arr[1] : 0x08
arr[2] : 0x16

분명 int형 배열인데 왜 4byte씩 증가되지 않고 8byte씩 증가 되었을까?
표현이 잘될런지는 모르지만 그림으로 설명하면 아래와 같이 설명할수있다.

arr[0] -------->   1  ,             2       
                         a[0][0]      a[0][1]
                         0x00           0x04   

arr[1] -------->   3  ,             4      
                        a[1][0]      a[1][1]
                         0x08           0x12  

arr[2] -------->   5  ,             6      
                        a[2][0]      a[2][1]
                         0x16           0x20  

arr[0]이 배열의 첫번째 행을 가르키는 것을 알수 있다 3*2배열이기 때문에 한 행에는 2개의 값이 있고 그행의 첫번째 주소를 가르키게 되는것이다.
arr[1]은 첫번째행의 두번째 요소를 가르키는것이아니라 두번째 행인 a[1][0]을 가르키는 것을 알수있수있다 그럼 위의 결과값이 왜 4byte씩 증가 되지 않고 8byte씩 증가 되었는지 우리는 그 결론은 여기서 찾을수 있다 2차원 배열의 포인터연산시 증가하는 값은 포인터의 자료형의메모리크기*행의 갯수!
행단위증가를 하는것을 알수있다.

[ 다차원 포인터타입 정의 ]
     - 가리키는 대상의 자료형
     - 포인터 연산시 증가하는 바이트의 크기

위에서 정의 내리기를 다차원 배열의 포인터 타입은 가리키는 대상과 포인터연산시 증가하는 바이트의 크기 가 같으면 같은포인터타입이라는것을 알수있다.

int array1[3][2];
int array2[2][3];
위와같이 두개배열의 포인터타입은 서로 일치할까요?
그렇죠.. 아닙니다 서로 가르키는 대상이 int형인건 같지만 포인터 연산시 증가하는 바이트의 크기가 틀리죠.. array1은 8byte , array2는 12byte씩 증가하게 됩니다.

이렇게해야 서로의 포인터타입이 같게 되는것이죠
int array1[3][2]
int array2[4][2]

그럼 위의 이차원 배열을 포인터에 대입해 보겠습니다.
int (*pp)[2] = array1;
어때요? 이해가 가나요? 어떻게 보면 복잡해보이고 헷갈릴수 있습니다.
우리는 int* pp[2]; 이런문장을 배웠기 때문일텐데요 이문장과 위의 문장은 완전히 다른 코드입니다.
int* pp[2] 를 해석하면 int형 포인터를 요소로 2개 갖고있는 배열 pp로 해석되고
int (*pp)[2] 를 해석하기보다는 읽어보는게 나을거 같다. 읽어보면 다음과 같다.
pp라는 포인터를 선언을 하는데 가르키는 자료형은 int형이고 포인터 연산을 했을시
int형메모리크기(4byte)*2byte 만큼 건너뛴다 라고 표현할수 있다.
표현이 좀 어려웠나요 하지만 이렇게 이해하는것이 가장 쉬울거 같네요..
물론 이건 제기준입니다.^^:

[ 2차원배열 포인터타입의 간단한 예 ]
#include <stdio.h>

void show(int (*pp)[4], int a){
    int i,j;
    for(i=0; i<a; i++){
        for(j=0; j<4; j++){
            printf("%d",pp[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int main(void){
    int array1[2][4] = {{1,2,3,4},{5,6,7,8}};
    int array2[3][4] = {{1},{2},{3}};

    show(array1, 2);
    show(array2, 3);

    return 0;
}

여기저기 굴러다니는 간단한 예제를 따와 봤습니다
테스트를 해보니 잘되더군요 이만한 예제가 없는듯해서.. 그리고 항상 깜밖깜밖잊는 내 머리를 위해서 준비한 예제지요^^: