easy software

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

C언어/포인터와 배열

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

JAVA 웹개발자 2015. 1. 27. 22:50

저번시간에 다뤘던 다차원배열과 포인터의 관계를 좀더 깊이있게 알아보도록 하겠습니다.

 

이번에는 마지막즈음에 여러가지 예제도 병행하면서, 포인터를 정복해 보도록 합시다.

 

다만 이번 글에서는 그림이 없습니다...

 

이유는 그림을 직접 그려보시란 뜻으로 제공하지 않는 것입니다.

 

 

int arr[2][4]; 와 완전히 일치하는 타입의 포인터 변수를 선언하려면 어떻게 해야 할까요?

 

int (*pArr)[4]; 로 선언하면 됩니다.

 

*pArr은 포인터란 뜻이고, 맨앞에 int는 int형 변수를 가리킨다는 뜻입니다.

 

그리고 맨 뒤에있는 [4]는 4칸씩 건너뛴다라는 의미입니다.

 

이들을 조합해보면 'int형 변수를 가리키며, 크기가 4x4(int형 이므로)씩 증가하는

 

pArr이라는 포인터 변수다' 라는 뜻이 됩니다.

 

int *a; 는 싱글 포인터입니다. 그리고 int **b;는 더블 포인터입니다.

 

하지만 int arr[2][4], double arr2[10][30]을 담을 수 있는 포인터변수는 마땅한 이름이 없습니다.

 

이들 포인터 타입을 결정짓는 힌트는 배열안에 들어있습니다.

 

int arr[2][4]에서 요소는 int이고, 가로의 길이는[4]이다.

 

이 부분이 바로 배열을 가리키는 포인터, 즉 배열포인터를 선언하는 열쇠인 것입니다.

 

 

제 설명을 보면서 int (*pArr)[4]에서 괄호를 빼면 안되나? 라는 생각을 가지셨나요?

 

int *pArr[4];

 

어디서 많이 보지 않으셨습니까?

 

바로 int형 포인터 변수를 저장할 4칸짜리 1차원 배열선언입니다.

 

괄호하나차이로 완전히 다른 선언이 되어버렸네요. 실수하지 않도록 주의합시다.

 

 

우리는 이제 2차원 배열을 함수에 전달할때 매개변수선언을 어떻게 해야하는지 압니다.

 

뭐 예를들어 int (*ptr)[3] 이런식으로 하면 되겠지요?

 

혹시 1차원배열을 함수에 전달할때 매개변수 선언 기억나시나요?

 

int *ptr 과 같이 했었습니다. 직관적으로 보기좋게 int ptr[] 이렇게도 사용을 했었지요.

 

2차원배열도 이부분은 동일합니다.

 

함수에서는 예외적으로 int ptr[][3]형식으로 선언할 수 있습니다.

 

직관적으로 보기좋으니, 배열을 전달할때는 이 방법이 좋겠죠?

 

 

이제 간단한 예제를 몇개 해보도록 하죠.

 

제가 물론 답도 제시해 드릴겁니다만, 답을 보지 않고 혼자힘으로 풀어보세요.

 

이 문제들을 풀 수 있다면, 포인터를 정복한거나 다름 없습니다.

 

 

제가 코드를 드릴테니 빈칸을 채워보시겠나요?

 

int main(void){

int* arr1[5];

int* arr2[3][5];

 

| 빈칸 | = arr1;

| 빈칸 | = arr2;

 

return 0;

}

 

 

첫번째 빈칸의 답은 무엇일까요?

 

arrr1은 1차원 배열이므로 배열 이름을 가리키는 변수의 타입만 알면 쉽게 해결할 수 있죠?

 

그러므로 답은 int** 형의 변수를 선언하면 됩니다.

 

두번째 빈칸의 답은 무엇일까요?

 

일단 int형 포인터 변수를 가리켜야 할것이고, 크기는 5씩 증가해야 겠네요.

 

그러므로 답은 int* (*p2)[5] 가 되겠습니다.

 

이 문제가 이해되지 않는다면, 위의 글을 다시 읽어보도록 하세요.

 

 

두번째 문제를 제시하겠습니다.

 

int main(void){

int arr1[3];

int arr2[4];

 

int arr3[3][4];

int arr4[2][4];

 

fct1(arr1, arr2);

fct2(arr3, arr4);

 

return0;

}

 

코드에서 fct1과 fct2 함수를 호출하고 있습니다.

 

이 함수는 인자를 받아야하는데요, 어떻게 인자를 받아야하는지 함수의 원형을 선언해 봅시다.

 

우선 fct1은 1차원 배열 두개를 인자로 받아야 합니다.

 

그러므로 void fct1(int* p1, int* p2) 정도로 선언해주면 되겠네요.

 

fct2는 2차원배열을 인자로 받으므로

 

void fct2(int (*p1)[4], int (*p2)[4]) 정도로 선언해주면 되겠습니다.

 

 

3번째 문제를 제시하겠습니다.

 

int main(void){

int* arr5[3];

int* arr6[3][5];

 

int** arr7[5];

int*** arr8[3][5];

 

fct3(arr5, arr6);

fct4(arr7, arr8);

 

return0;

}

 

이번에도 두번째 문제와 마찬가지로 fct3와 fct4의 함수원형을 작성해보세요.

 

혼자힘으로 먼저 풀어보고 아래의 답을 확인하시기 바랍니다.

 

fct3함수의 경우 arr5와 arr6을 전달받고 있습니다.

 

arr5는 int형 포인터 배열이고, arr6은 int형 포인터 2차원 배열이네요.

 

1차원배열은 문제없습니다. 다만 2차원 배열이 조금 햇갈리실 수 있겠네요.

 

arr6은 int*로 이루어진 2차원 배열입니다.

 

그러므로 함수내에서 포인터를 선언할때에도 우선 int*를 가리키도록 해야겠죠.

 

그리고 가로의 길이가 5입니다. 그럼 감이 잡히시나요?

 

void fct3(int** p1, int* (*p2)[5]) 로 작성해주시면 되겠습니다.

 

이번에는 fct4를 보시죠. 정말 어려워 보일 수 있지만 별거없습니다.

 

이번에도 1차원 배열은 문제가 되지않죠?

 

arr8은 어떻게 해야 할까요?

 

배열은 int형 3중 포인터를 저장하고 있기 때문에, 함수내에서 선언해야할

 

매개변수에서도 int***를 우선 적어야겠네요.

 

그리고 가로의 길이는5이므로 맨 끝에는 [5]를 적어주면 되겠습니다.

 

그리고 변수에 이름을 정해주는데, 포인터로 정해주면 되겠죠?

 

답은 void fct4(int*** p1, int*** (*p2)[5]) 로 작성해주시면 되겠습니다.

 

 

 

위의 문제들을 모두 혼자힘으로, 그리고 그림을 통해서 해결하셨다면

 

포인터를 모두 이해한거나 마찬가지라고 생각합니다.

 

모두 수고하셨습니다.

 

 

이번 글은 여기서 마치도록 하겠습니다.

Comments