1차원 배열을 함수의 인자로 받는다면 다음과 같이 선언될 수 있습니다.
int arr[10];
func(arr);
void func(int *arr) { ... }
함수를 다음과 같이 선언해도 됩니다.
void func(int arr[]) { ... }
이것은 이전에 설명 드린바 있습니다.
2차원 배열을 함수로 넘긴다면 어떨까요?
'1차원배열을 포인터 변수로 받았으니 2차원 배열은 이중포인터 변수로 받으면 되겠구나!'라고 생각할 수 있습니다.
다음과 같은 형태가 되겠네요.
int arr[3][3];
func(arr);
void func(int **arr) { ... } // 이것은 잘못된 호출입니다.
2차원 배열 arr은 int** 자료형이 아닙니다.
arr이 실제 가리키는 것은 arr[0] 입니다. arr의 자료형은 arr 배열의 하나의 행이라고 볼수 있습니다.
#include <stdio.h>
int main(void) {
int arr[3][3];
printf("arr 주소 : %p | 길이 : %d\n", arr, sizeof(arr));
printf("arr[0] 주소 : %p | 길이 : %d\n", arr[0], sizeof(arr[0]));
printf("arr[1] 주소 : %p | 길이 : %d\n", arr[1], sizeof(arr[1]));
printf("arr[2] 주소 : %p | 길이 : %d\n", arr[2], sizeof(arr[2]));
return 0;
}
arr은 배열을 가리키는 포인터입니다.
포인터는 증감연산을 할 수 있습니다. 2차원 배열에서 포인터의 이름을 기반으로 증감연산을 한다면 다음과 같습니다.
#include <stdio.h>
int main(void) {
int arr[3][3];
printf("arr 주소 : %p\n", arr);
printf("arr+1 주소 : %p\n", arr + 1);
printf("arr+2 주소 : %p\n", arr + 2);
return 0;
}
arr + 1의 결과는 arr[0]의 사이즈인 12 만큼 이동했습니다.
arr + 2의 결과는 arr[0]의 사이즈인 24 만큼 이동했습니다.
이처럼 포인터는 증감 연산을 했을때 자료형의 크기만큼 이동해야 합니다.
정리를 해보면 다음과 같은 배열이 있을때
int arr[3][3];
위와 같은 형태의 포인터는 다음과 같이 선언할 수 있습니다.
int (*ptr)[3]; // 배열 포인터 선언
다음은 포인터배열 선언입니다 해깔리면 안되요!!
int * ptr[3]; // 포인터 배열 선언
다음과 같은 형식이 되어야 합니다.
int arr[3][4];
func(arr);
func(int (*parr)[4]) { ... } // 이렇게 하거나
func(int parr[][4]) { ... } // 또는 이렇게 합니다.
(*parr)[4]와 parr[][4]는 동일한 표현입니다.
다음은 2차원 배열을 받아 배열요소를 출력합니다.
#include <stdio.h>
#define COL 4
void showArr(int(*arr)[COL], const int ROW);
void main(void) {
int arr[][COL] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
};
int len = sizeof(arr) / sizeof(arr[1]);
showArr(arr, len);
return;
}
void showArr(int (*arr)[COL], const int ROW) {
int i, j;
for (i = 0; i < ROW; i++) {
for (j = 0; j < COL; j++) {
printf("%2d ", arr[i][j]);
}
printf("\n");
}
}
배열과 포인터에서 다음은 같은 의미입니다.
arr[i] == *(arr+i) // 같다
2차원배열에서의 포인터식은 다음과 같습니다.
arr[i][j] == *(arr[i]+j) == (*(arr+i))[j] == *(*(arr+i)+j) // 같다
다음 코드에서 확인해보겠습니다.
#include <stdio.h>
int main(void) {
int arr[][4] = { { 1,2,3,4 },{ 5,6,7,8 } };
int i = 1, j = 2;
printf(" arr[i][j] : %d\n", arr[i][j]);
printf(" *(arr[i]+j) : %d\n", *(arr[i] + j));
printf(" (*(arr+i))[j] : %d\n", (*(arr + i))[j]);
printf(" *(*(arr+i)+j) : %d\n", *(*(arr + i) + j));
return 0;
}
소괄호가 난무하는것은 *(간접지정연산자)가 덧셈 뺄셈 연산자보다 우선순위가 높기 때문입니다. 그렇기 때문에 주의하셔야 합니다.
포인터에 먼저 증감 연산을 하여 주소를 이동시킨후 가리켜서 값에 접근해야 합니다.
다음 코드에서 빈칸에 들어갈 적절한 포인터 변수를 선언하세요.
int main(void) {
int * arr1[5];
int * arr2[3][5];
= arr1;
= arr2;
return 0;
}