1차원 배열과 포인터에 대해서는 포스팅을 했다.
그런데 1차원 배열과 포인터 보다 더 중요한 2차원 배열과 포인터에 대한 내용을 포스팅 해보도록 하겠다.
기본적으로 1차원 배열도 많이 사용하지만 2차원 배열을 사용해야 할때 또한 다분히 존제 한다.
우선 기본 소스를 우선 보고 하나하나 찾아가 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | int main(){ int i, j; int imsi[3][2] = {{6,3},{9,1},{7,2}}; int (*imsip)[2]; // 선언 imsip = imsi; // A for(i = 0; i < 3; i++){ for(j=0;j<2;j++){ printf("[%d][%d] %d\n", i, j, *(*(imsip + i)+j)); // B } } for(i = 0; i < 3; i++){ for(j=0;j<2;j++){ printf("[%d][%d] %d\n", i, j, *(imsip[i]+j)); // C } } for(i = 0; i < 3; i++){ for(j=0;j<2;j++){ printf("[%d][%d] %d\n", i, j, imsip[i][j]); // D } } for(i = 0; i < 3; i++){ for(j=0;j<2;j++){ printf("[%d][%d] %d\n", i, j, imsi[i][j]); // E } } } |
이 소스를 보면 B, C, D, E가 모두 같은 결과를 가져 온다. 하나 하나 알아 보도록 하겠다.
2차원 배열에서 알아둘것은 우선 '선언'부분이다.
이 부분이 포인터를 사용하게 하는데 많은 시행착오를 만들어 낸다.
선언을 잘 기억 해 두어야 할 것이다.
선언을 중요한 이유에 대해서 예제를 통해 한번 확인 해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include<stdio.h> int main(){ int imsi[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; int i, j; int *intp; intp = imsi; for ( i = 0; i < 3; i++) { for (j = 0; j < 2; j++) { printf("[%d][%d] = %d\n", i, j, imsi[i][j]); } } for ( i = 0; i < 3; i++) { printf("%d \n", intp + i); // A } printf("\n"); for ( i = 0; i < 3; i++) { printf("%d \n", imsi[i]); // B } } |
예기서 우리가 알아야 할 사실은 단 한가지 뿐이다. 포인터 변수는 1차원 배열만을 받아 들인다는 것이다.
1차원 배열만 갖을 수 있는 아이들이기 때문에 그 포인터들의 배열을 갖는 다면 2차원 배열이 되는 것이다.
말을 쉽게 하자면 포인터 패열을 저장할 수 있는 (*pint)의 배열 문법 각괄호([])를 사용하면 되는 것이다.
여기서 괄호는 아주 중요한 열활을 한다. 연산자 우선순위가 머리에 명확하게 있는 사람이 아니라면 괄호가 들어갈 부분을 논리적으로 생각하여 괄호를 하는 것이 좋다.
가장 많이 실수 할 수 있는 코드다.
1 2 3 4 5 6 7 8 9 | int main(){ int imsi[3][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 } }; int i, j; int (*pint1)[2]; // A int* pint2[3]; // B } |
에서도 언급한 내용이지만 포인터는 일반적인 변수 타입중 하나라고 받아들임으로써 해깔리지 않을 수 있는 것이다.
2차원 배열과 포인터에서는 가장 핵심이 되는 내용이다. 이걸 이해하면 다른 것또한 쉽게 이해가 갈것이다.
이제 한가지 재미 있는 실험을 해보려고 한다.
실험에 들어가기 앞서 실험과 관련되어 있는 문제 하나를 풀고 넘어 갔으면 좋겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | int main(){ int imsi[2]; int* pimsi; pimsi = imsi; printf("imsi[2] = %d \n", sizeof(imsi)); printf("pimsi = %d \n", sizeof(pimsi)); printf("*pimsi = %d ", sizeof(*pimsi)); printf("\n"); } |
1 2 3 4 5 6 7 8 9 10 | int main(){ int imsi[3][2] = { { 1, 2 }, { 3, 4 }, {5,6} }; int (*pimsi)[2]; pimsi = imsi; pimsi = imsi[0]; pimsi = &imsi[0][0]; } |
위의 예제를 보면 2차원 배열이 시작하는 부분의 주소를 다양하게 표현하여 포인터 배열에 넣었다.
정말 다 똑같은 것일까???
1 2 3 4 5 6 7 8 9 10 | int main(){ int imsi[3][2] = { { 1, 2 }, { 3, 4 }, {5,6} }; printf("imsi = %d \taddr = %x \n",sizeof(imsi), imsi); printf("imsi[0] = %d \taddr = %x \n", sizeof(imsi[0]), imsi[0]); printf("&imsi[0][0] = %d \taddr = %x \n", sizeof(&imsi[0][0]), &imsi[0][0]); printf(""); } |
결과는 보면 아주 명확해 질것이다.
주소는 똑같지만 배열의 크기가 다르게 표현이 된다.
배열과 포인터를 엮어서 생각하면 아주 재미 있는 것들을 할 수 있다.
하지만 배열과 포인터의 특성을 정확하게 이해 하고 사용하는 것이 선행 되어야 할 것이다.
2차원 배열과 포인터 끝.....
'C, C++' 카테고리의 다른 글
[c언어]값에 의한 호출 대 참조에 의한 호출 (call by value vs call by reference) (2) | 2016.01.26 |
---|---|
[c언어] void 포인터 (0) | 2016.01.26 |
[C언어] 1차원 배열과 포인터 (0) | 2014.06.29 |
[C언어]포인터의 기초(pointer) (0) | 2014.06.26 |