2차원 배열 이름의 포인터 형
2차원 배열 이름이 가리키는 것들
#include <stdio.h>
int main(void)
{
int arr2d[3][3];
printf("%d\n", arr2d);
printf("%d\n", arr2d[0]);
printf("%d\n\n", &arr2d[0][0]);
printf("%d\n", arr2d[1]);
printf("%d\n\n", &arr2d[1][0]);
printf("%d\n", arr2d[2]);
printf("%d\n\n", &arr2d[2][0]);
printf("sizeof(arr2d): %lu\n", sizeof(arr2d));
printf("sizeof(arr2d[0]): %lu\n", sizeof(arr2d[0]));
printf("sizeof(arr2d[1]): %lu\n", sizeof(arr2d[1]));
printf("sizeof(arr2d[2]): %lu\n", sizeof(arr2d[2]));
return 0;
}
/* 결과
1795043140
1795043140
1795043140
1795043152
1795043152
1795043164
1795043164
sizeof(arr2d): 36
sizeof(arr2d[0]): 12
sizeof(arr2d[1]): 12
sizeof(arr2d[2]): 12
배열 이름 arr2d를 대상으로 sizeof 연산을 하는 경우 배열 전체의 크기를 반환
arr2d[0], arr2d[1], arr2d[2]를 대상으로 sizeof 연산을 하는 경우 각 행의 크기를 반환
arr2d는 첫 번째 요소를 가리키면서 배열 전체를 의마한다. 하지만, arr2d[0]은 첫 번째 요소를 가리키되 1행만을 의미한다.
*/
배열 이름 기반의 포인터 연산: 배열 이름에 1을 더한 결과는?
두 포인터의 포인터 형이 같다면, 두 포인터를 대상으로 하는 증가 및 감소 연산의 결과로 증가 및 감소하는 값의 크기는 동일하다.
#include <stdio.h>
int main(void)
{
int arr1[3][2];
int arr2[2][3];
printf("arr1: %p\n", arr1);
printf("arr1+1: %p\n", arr1+1);
printf("arr1+2: %p\n", arr1+2);
printf("arr2: %p\n", arr2);
printf("arr2+1: %p\n", arr2+1);
return 0;
}
/* 결과
arr1: 0x16db4ef50
arr1+1: 0x16db4ef58
arr1+2: 0x16db4ef60
arr2: 0x16db4ef38
arr2+1: 0x16db4ef44
2차원 배열 이름을 대상으로 증감 연산을 할 경우, 연산 결과는 각 행의 첫 번째 요소의 주소 값이 됌
때문에 자료형이 동일하더라도 배열의 가로길이가 다르다면, 포인터 형이 다르다.
*/
최종 결론! 2차원 배열 이름의 포인터 형
2차원 배열 이름의 포인터 형에는 두 가지 정보가 담겨야 함.
가리키는 대상은 무엇인가
배열 이름(포인터)를 대상으로 값을 1 증가 및 감소 시 실제로는 얼마가 증가 및 감소하는가
int arr[3][4];
// arr은 가리키는 대상이 int형 변수이고, 포인터 연산 시 sizeof(int) x 4의 크기 단위로 증가 및 감소하는 포인터 형이다.
포인터 변수의 선언
int (*ptr) [4];
/*
int: int형 변수를 가리키는 포인터!
(*ptr): ptr은 포인터!
[4]: 포인터 연산 시 4칸 씩 건너뛰는 포인터!
이러한 변수는 2차원 배열을 가리키는 용도로만 사용되기 때문에 '배열 포인터 변수'라 한다.
*/
#include <stdio.h>
int main(void)
{
int arr1[2][2]={
{1, 2}, {3, 4}
};
int arr2[3][2]={
{1, 2}, {3, 4}, {5, 6}
};
int arr3[4][2]={
{1, 2}, {3, 4}, {5, 6}, {7, 8}
};
int (*ptr) [2];
int i;
ptr=arr1;
printf("** Show 2,2 arr1 **\n");
for(i=0 ; i<2 ; i++)
printf("%d %d\n", ptr[i][0], ptr[i][1]);
ptr=arr2;
printf("** Show 3,2 arr2 **\n");
for(i=0 ; i<3 ; i++)
printf("%d %d\n", ptr[i][0], ptr[i][1]);
ptr=arr3;
printf("** Show 4,2 arr3 **\n");
for(i=0 ; i<4 ; i++)
printf("%d %d\n", ptr[i][0], ptr[i][1]);
return 0;
}
/* 결과
** Show 2,2 arr1 **
1 2
3 4
** Show 3,2 arr2 **
1 2
3 4
5 6
** Show 4,2 arr3 **
1 2
3 4
5 6
7 8
*/
2차원 배열 이름의 특성과 주의 사항
포인터 배열과 배열 포인터의 차이
#include <stdio.h>
int main(void)
{
int num1=10, num2=20, num3=30, num4=40;
int arr2d[2][4]={1, 2, 3, 4, 5, 6, 7, 8};
int i, j;
int * whoA[4]={&num1, &num2, &num3, &num4}; // 포인터 배열
int (*whoB)[4]=arr2d; // 배열 포인터
printf("%d %d %d %d\n", *whoA[0], *whoA[1], *whoA[2], *whoA[3]);
for(i=0 ; i<2 ; i++)
{
for(j=0 ; j<4 ; j++)
printf("%d ", whoB[i][j]);
printf("\n");
}
return 0;
}
/* 결과
10 20 30 40
1 2 3 4
5 6 7 8
*/
2차원 배열을 함수의 인자로 전달하기
int main(void)
{
int arr1[2][7];
double arr2[4][5];
SimpleFunc(arr1, arr2);
. . . .
}
/*
arr1의 주소 값을 전달 받을 수 있는 매개 변수의 이름을 parr1,
arr2의 주소 값을 전달 받을 수 있는 매개 변수의 이름을 parr2
*/
int (*parr1)[7]
double (*parr2)[5]
// 따라서 SimpleFunc 함수가 void 형이라고 가정하면 아래처럼 선언
void SimpleFunc(int (*parr1)[7], double (*parr2)[5]) { . . . . }
#include <stdio.h>
void ShowArr2DStyle(int (*arr)[4], int column) // 배열 요소 전체 출력
{
int i, j;
for(i=0 ; i<column ; i++)
{
for(j=0 ; j<4 ; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
printf("\n");
}
int Sum2DArr(int arr[][4], int column) // 배열 요소의 합 반환
{
int i, j, sum=0;
for(i=0 ; i<column ; i++)
for(j=0 ; j<4 ; j++)
sum += arr[i][j];
return sum;
}
int main(void)
{
int arr1[2][4]={1, 2, 3, 4, 5, 6, 7, 8};
int arr2[3][4]={1, 1, 1, 1, 3, 3, 3, 3, 5, 5, 5, 5};
ShowArr2DStyle(arr1, sizeof(arr1)/sizeof(arr1[0]));
ShowArr2DStyle(arr2, sizeof(arr2)/sizeof(arr2[0]));
printf("arr1의 합: %d\n", Sum2DArr(arr1, sizeof(arr1)/sizeof(arr1[0])));
printf("arr2의 합: %d\n", Sum2DArr(arr2, sizeof(arr2)/sizeof(arr2[0])));
return 0;
}
/* 결과
1 2 3 4
5 6 7 8
1 1 1 1
3 3 3 3
5 5 5 5
arr1의 합: 36
arr2의 합: 36
두 함수의 두 번째 매개변수를 배열의 세로길이를 전달받는다. 따라서 가로 길이가 4인 int형 2차원 배열이라면 세로 길이에 상관 없이 인자로 전달이 가능
sizeof(arr1) / sizeof(arr1[0])
sizeof(arr1) / sizeof(arr1[0])
배열의 전체 크기 / 배열의 가로 크기 = 배열의 세로 길이
*/
2차원 배열에서도 arr[i]와 *(arr+i)는 같다.
// 1차원 배열
arr[i] == *(arr+i) // arr[i]는 *(arr+i)와 같다.
// 이 식은 다차원 배열에서도 성립
#include <stdio.h>
int main(void)
{
int a[3][2]={{1, 2}, {3, 4}, {5, 6}};
printf("a[0]: %p\n", a[0]);
printf("*(a+0): %p\n", *(a+0));
printf("a[1]: %p\n", a[1]);
printf("*(a+1): %p\n", *(a+1));
printf("a[2]: %p\n", a[2]);
printf("*(a+2): %p\n", *(a+2));
printf("%d, %d\n", a[2][1], (*(a+2))[1]);
printf("%d, %d\n", a[2][1], *(a[2]+1));
printf("%d, %d\n", a[2][1], *(*(a+2)+1));
return 0;
}
/* 결과
Chapter18/"2DArrAccessType
a[0]: 0x16f092f40
*(a+0): 0x16f092f40
a[1]: 0x16f092f48
*(a+1): 0x16f092f48
a[2]: 0x16f092f50
*(a+2): 0x16f092f50
6, 6
6, 6
6, 6
*/