주의! '배열 포인터'와 '포인터 배열'을 혼동하지 말자.
int* whoA[4]; // 포인터 배열
int (*whoB)[4]; // 배열 포인터
whoA와 whoB의 외형적 유일한 차이점은 소괄호의 유무
whoA : 배열 선언 → int형 포인터 변수로 이뤄진 int형 포인터 배열
whoB : 포인터 변수 선언 →가로길이가 4인 int형 2차원 배열을 가리키는 용도의 포인터 변수
예제
#include <stdio.h>
int main(void)
{
int num1 = 10;
int num2 = 20;
int num3 = 30;
int num4 = 40;
int arr2d[2][4] = { 1, 2, 3, 4, 5, 6, 7, 8 };
/* 포인터 배열 */
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 (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
printf("%d ", whoB[i][j]);
printf("\n");
}
}
2차원 배열을 함수의 인자로 전달하기
아래의 코드에서 호출되고 있는 simplefunc 함수의 원형
int main(void)
{
int arr1[2][7];
double arr2[4][5];
simplefunc(arr1, arr2);
}
arr1의 주소 값을 전달받을 수 있는 매개변수의 이름을 parr1
arr2의 주소 값을 전달받을 수 있는 매개변수의 이름을 parr2
아래와 같이 배열 포인터 선언
int (*parr1)[7]
double (*parr2)[5]
따라서 simplefuc 함수의 반환형이 void라고 가정하면 함수는 다음의 형태로 정의
void simplefunc(int (*parr1)[7], double (*parr2)[5]) {....}
다음과 같이 정의도 가능
void simplefunc(int parr1[][7], double parr2[][5]) {....}
예제
#include <stdio.h>
void showarr(int(*arr)[4], int column) {
for (int i = 0; i < column; i++)
{
for (int j = 0; j < 4; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
printf("\n");
}
int sum2d(int arr[][4], int column)
{
int sum = 0;
for (int i = 0; i < column; i++)
for (int 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 };
showarr(arr1, sizeof(arr1) / sizeof(arr1[0])); // 한 행에 대한 메모리 합 / 전체 메모리
showarr(arr2, sizeof(arr2) / sizeof(arr2[0]));
printf("arr1의 합 : %d \n", sum2d(arr1, sizeof(arr1) / sizeof(arr1[0])));
printf("arr2의 합 : %d \n", sum2d(arr2, sizeof(arr2) / sizeof(arr2[0])));
}
두 매개변수의 선언이 중요함
void showarr(int(*arr)[4], int column) {....}
int sum2d(int arr[][4], int column) {....}
두 번째 매개변수를 통해서 배열의 세로길이를 전달 받는다.
다음의 형태로 세로 길이를 계산
sizeof(arr1) / sizeof(arr1[0])
sizeof(arr2) / sizeof(arr2[0])
sizeof(arr1)과 sizeof(arr2)의 반환 값은 배열의 전체 크기
sizeof(arr1[0])과 sizeof(arr2[0])의 반환 값은 배열의 가로크기
따라서 위의 연산은 세로의 길이 → 써먹을 일이 많이 있음
2차원 배열에서도 arr[i]과 *(arr + i)는 동일하다
arr[i] == *(arr + i) // arr[i]는 *(arr+i)와 같다
복습
int arr[3][2] = { {1,2}, {3, 4}, {5, 6} };
이 배열에서 6이 저장된 인덱스 [2][1]의 위치의 값을 4로 변경시키기 위해서는 다음의 문장을 실행해야 함
arr[2][1] = 4;
다음 문장들로 대체할 수 있음
(*(arr+2))[1] = 4;
*(arr[2]+1) = 4;
*(*(arr+2)+1) = 4;
1. 첫 번째 식은
arr[2][1]=4에서 arr[2]를 *(arr+2)로 바꿈으로써 쉽게 구할 수 있다.
2. 두 번째 식은 치환이 필요하다
arr[2][1] = 4에서 arr[2]를 A로 치환하면 다음과 같이 변환이 된다.
A[1]=4 → *(A+1)=4
3. 마지막 식은 두 번째 식을 변경하면 된다.
arr[2] = *(arr+2)
*(arr[2] + 1) = 4 → *(*(arr+2) + 1) = 4;
예제를 한 번 살펴보자
#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;
}
참고 : [윤성우 열혈 C 프로그래밍] - 대부분의 내용 및 코드는 이 책에서 개인 공부 정리 목적으로 참고하였습니다.
'Language&Framework&Etc > C' 카테고리의 다른 글
함수 포인터와 void 포인터(19-2) main 함수로의 인자 전달 (0) | 2020.12.10 |
---|---|
함수 포인터와 void 포인터(19-1) 함수 포인터와 void 포인터 (0) | 2020.12.10 |
다차원 배열과 포인터의 관계(18-1) 2차원 배열 이름의 포인터형 (0) | 2020.12.10 |
포인터의 포인터(17-2) 다중 포인터 변수와 포인터의 필요성 (0) | 2020.12.10 |
포인터의 포인터(17-1) 포인터의 포인터에 대한 이해 (0) | 2020.12.09 |