easy software

C언어 다차원 배열과 포인터의 이해3 본문

C언어/포인터와 배열

C언어 다차원 배열과 포인터의 이해3

JAVA 웹개발자 2015. 1. 27. 23:29

포인터 부분이 조금 길어져서 죄송합니다.

 

그만큼 중요한 내용이라고 생각하시고, 잘 따라와 주시기 바랍니다.

 

저도 부족하지만 최선을 다하겠습니다.

 

그리고 이 글을 처음 보시는 분들은 제목에 써져있는 만큼 앞에 1, 2강이 따로 있습니다.

 

원하는 정보가 없다면 1과 2강을 참고해주시기 바랍니다.

 

저도모르게 강의라고 하니까 쫌 우습네요. 그냥 정보라고 하겠습니다.

 

 

이번시간에는 다차원 배열과 포인터의 이해2에 이어서 진행하도록 하겠습니다.

 

다차원 배열과 포인터의 이해2에서 문제 2번과 3번을 봐주세요.

 

Ctrl+n 을 누르시면 편리하게 두개의 창을 띄워놓고 보실 수 있습니다.

 

문제 2와 3의 답을 구하셨고, 구하지 못했더라도 제 답을 보셨죠?

 

그런데 문제 2와 3에서는 제가 구한 답말고도 다른 답이 있습니다.

 

그 답을 찾아보세요.

 

답은 바로 밑에서 보여드릴거지만, 일단 혼자 풀어보세요.

 

 

풀어 보셨나요?

 

답은 void fct1(int p1[], int p2[])

 void fct2(int p1[][4], int p2[][4])

 void fct3(int* p1[], int* p2[][5])

 void fct4(int** p1[], int*** p2[][5]) 입니다.

 

이유가 무엇일까요?

 

예전에 제가 작성한 글에서 *p1 = = p[] 이다 라고 말씀드린적이 있습니다.

 

그 개념을 똑같이 적용시키면 위와 같은 답이 나오게 되는것이죠.

 

위와같이 작성하게되면, '배열을 전달하는구나'라고 의미를 알 수 있게됩니다.

 

 

2차원 배열에서 arr[i]와 *(arr+i)

 

arr[i]= = *(arr+i)은 arr이 포인터 변수이거나 배열 이름인 경우에 항상 성립합니다.

 

그것은 2차원 배열도 동일하죠.

 

아래의 예를 들어서 설명해 드리겠습니다.

 

int main(void){

int a[3][2] = { {1, 2}, {3, 4}, {5, 6} };

 

printf("a[0]    : %d \n", a[0]);

printf("*(a+0) : %d \n", *(a+0));

 

printf("a[1]    : %d \n", a[1]);

printf("*(a+1) : %d \n", *(a+1));

 

printf("a[2]    : %d \n", a[2]);

printf("*(a+2) : %d \n", *(a+2));

 

printf("%d, %d \n", a[1][0], (*(a+1))[0]);

printf("%d, %d \n", a[1][2], *(a[1]+2));

printf("%d, %d \n", a[2][1], *(*(a+2)+1));

 

return 0;

}

 

 

코드를 실행하면 아래와 같이 출력됩니다.

 

 

 

 

분명 다른 연산들이 이루어졌는데, 결과가 동일하게 나오고있습니다. 왜그런지 증명해 봅시다.

 

 a[1][0]은 (*(a+1))[0]과 어떻게 같을까요?

 

a[1]은 *(a+1)과 같습니다. 따라서 a[1][0]에서 a[1]을 대신해서 *(a+1)을 넣으면?

 

(*(a+1))[0]이 됩니다!

 

a[1][2]와 *(a[1]+2)은 어떻게 같을까요?

 

a[1]을 A라는 문자로 치환해봅시다! 그럼 A[2]가 되죠?

 

이는 *(A+2)와 같습니다. A를 a[1]로 되돌리면? *(a[1]+2)가 됩니다!

 

a[2][1]과 *(*(a+2)+1)도 같은데요, 치환을 이용해서 직접 풀어보시기 바랍니다!

 

 

 

그럼 이번에는 조금 어려운문제를 풀어보면서 확실하게 이해를 해보도록 합시다!

 

int a[10][10]을 선언했다고 가정하겠습니다.

 

1. a[i][j]

2. *(a[i]+j)

3. (*(a+i))[j]

4. *(*(a+i)+j)

 

위의 네 문장은 같은 의미를 지니는 문장입니다. 이를 증명해 보시기바랍니다.

 

치환을 적극 이용해서 문제를 풀어보세요.

 

문제를 풀다가 막히면 아래의 답을 확인해주시기 바랍니다.

 

 

 

1번을 2번으로 변환해보겠습니다. a[i][j] - A[j] - *(A+j) - *(a[i]+j)

 

2번을 4번으로 변환해보겠습니다. *(a[i]+j) - *(*(a+i)+j)

 

4번을 3번으로 변환해보겠습니다. *(*(a+i)+j) - *(A+j) - A[j] - (*(a+i))[j]

 

 

프로그래밍언어를 공부하고, 실제로 적용할때에는 쉬운 방법이 있으면

 

쉬운방법으로 코드를 작성해야 합니다.

 

위와같이 치환을 이용해서 하는분들도 물론 계실겁니다.

 

하지만 가능하면 쉬운 코드로 작성해주시기 바랍니다.

 

그러면 두번째 문제입니다.

 

int arr[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};

printf("arr[1][0][1] : %d \n", arr[1][0][1]);

 

위의 코드는 3차원 배열에서 [1][0][1]인덱스에 접근하는 코드입니다.

 

3차원 배열이라고해서 어려울 것 없습니다.

 

위의 첫 번째 문제의 증명을 하셨다면 치환을 이용해서 쉽게 풀 수 있는 문제입니다.

 

저는 사실 애를 많이 먹었지만, 여러분들은 쉽게하실 수 있을거에요.

 

그럼 [1,0,1]인 요소에 접근할 수 있는 다른 문장 5가지를 제시해 보시기 바랍니다.

 

답은 아래에 있으나, 반드시 혼자 풀어보세요.

 

 

첫번째 제시 : arr[1][0][1] - (*(a+1))[0][1]

두번째 제시 : (*(a+1))[0][1] - A[0][1] - *(A+0)[1] - (*(*(arr+1)+0))[1]

세번째 제시 : (*(*(arr+1)+0))[1] - A[1] - *(A+1) - *(*(*(arr+1)+0))+1

네번째 제시 : arr[1][0][1] - A[1] - *(A+1) - *(arr[1][0])+1

다섯번째 제시 : *(arr[1][0])+1 - *(A[0])+1 - *(*(A+0))+1 - *(*(arr[1]+0)+1)

 

잘 풀어보셨나요?

 

치환만 잘 이용한다면 크게 어렵지 않은 문제입니다.

 

하지만 실제 코드를 작성할 때에는 위와같이 어렵게 작성하지마시고, 쉬운방법을 이용하세요.

 

 

 

포인터가 무척 어렵고, C언어에서는 포인터없인 코드작성이 불가능하다란 소릴 들어본적이 있습니다.

 

하지만, 맞는 말은 아닌거 같아요. 그만큼 중요하기 때문에 저런 말이 나온게 아닌가 싶습니다.

 

중요한 만큼 반드시 100%이해해주시기 부탁드립니다.

Comments