본문으로 바로가기

   

 

1차원 배열이름의 포인터 형
int arr[10]; // arr은 int형 포인터
여기서 arr은 int형 포인터이다. 따라서 다음과 같이 함수의 인자로 전달되기 위해서는, 
SimpleFunc(arr);
함수의 매개변수가 다음과 같이 int형 포인터로 선언되어야 한다.
void SimpleFunc(int * ptr){..}
그리고 int * parr[20]; 이러한 포인터 배열의 이름 parr이 int **형 포인터이다.

2차원 배열이름의 포인터 형을 결정지으려면 우선 2차원 배열이름이 가리키는 대상이 무엇인지 알 아야 한다. 그런데 1차원 배열과 달리 이것만으로 포인터 형이 결정되지 않는다.

 

2차원 배열의 경우 arr2d[0], arr2d[1], arr2d[2]도 의미를 지닌다. 각각 1행, 2행, 3행의 첫 번째 요소를 가리키는 주소 값의 의미를 지닌다

 

그럼 여기서 arr2d와 arr2d[0]는 같은 것인가?

#include <stdio.h>

void main()
{
	int arr2d[3][3];
	printf("%d\n", arr2d);
	printf("%d\n", arr2d[0]);
	printf("%d\n", &arr2d[0][0]);

	printf("\n");

	printf("%d\n", arr2d[1]);
	printf("%d\n", &arr2d[1][0]);

	printf("\n");

	printf("%d\n", arr2d[2]);
	printf("%d\n", &arr2d[2][0]);

	printf("\n");

	printf("sizeof(arr2d): %d\n", sizeof(arr2d));
	printf("sizeof(arr2d[0]): %d\n", sizeof(arr2d[0]));
	printf("sizeof(arr2d[1]): %d\n", sizeof(arr2d[1]));
	printf("sizeof(arr2d[2]): %d\n", sizeof(arr2d[2]));
}

 


arr2d는 첫 번째 요소를 가리키면서 배열 전체를 의미한다.
하지만, arr2d[0]은 첫 번째 요소를 가리키되 1행만을 의미한다. 그래서 sizeof 연산의 결과가 다른 것이다.
즉, arr2d와 arr2d[0]은 서로 다른 것이다.

 

연산결과는 각 행의 첫 번째 요소의 주소값이 된다. 즉, arr1이  1행의 첫 번째 요소를 가리키면 , arr1 + 1이 반환하는 주소 값은 2행의 첫 번째 요소를 가리키게 되고, arr1 + 2가 반환하는 주소 값은 3행의 첫 번째 요소를 가리키게 된다. 때문에 2차원배열을 이루는 요소의 자료형이 동일하더라도 배열의 가로 길이가 다르면 위 그림에서 보인 바와 같이 배열 이름을 대상으로 하는 포인터 연산의 결과는 달라진다.

 

2차원 배열 이름의 포인터 형은 가로의 길이에 따라서도 달라진다.

int arr[3][4]; // arr은 가리키는 대상이 int형 변수이고, 포인터 연산 시 sizeof(int)x4의 크기 단위
                // 값이 증가 및 감소하는 포인터 변수 ptr
가리키는 대상이 int형 변수이면서 포인터 연산 시 sizeof(int)x4의 크기 단위로 증가 및감소하는 포인터 변수 ptr은 다음과 같이 선언한다.    
int(*ptr)[4];

char (*arr1)[4]; 
//arr1은 char형 변수를 가리키면서, 포인터 연산시 char x 4의 단위로 증가 및 감소하는 포인터 변수
double (*arr2)[7];
//arr2는 double형 변수를 가리키면서, 포인터 연산시 double x 7의 단위로 증가 및 감소하는 포인터 변수

#include <stdio.h>
//예제
void main() {
	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;
	for (i = 0; i < 2; i++)
		printf("%d %d\n", ptr[i][0], ptr[i][1]); // 1 2 3 4

	ptr = arr2;
	for (i = 0; i < 3; i++)
		printf("%d %d\n", ptr[i][0], ptr[i][1]); // 1 2 3 4 5 6

	ptr = arr3;
	for (i = 0; i < 4; i++)
		printf("%d %d\n", ptr[i][0], ptr[i][1]); // 1 2 3 4 5 6 7 8

	}

}

 

 

포인터 배열과 배열 포인터(둘은 완전히 다르다)
int * whoA [4]; // 포인터 배열 => 배열 선언 => int형 포인터 배열
int (*whoB)[4]; // 배열 포인터 => 포인터 변수 선언 => 가로 길이가 4인 int형 2차원 배열을 가리키는 용도의 포인터 변수

2차원 배열에서도 arr[i]와 *(arr+i)는 같다.
arr[i] == *(arr+i) 그런데 이는 다음의 문장들로 대신할 수 있다.
(*(arr+2))[1] = 4;
*(arr[2]+1)=4;
*(*arr+2)+1)=4;


문제1)
아래에서 보이는 main함수에서 물음표 ???을 대신 할 수 있는 포인터 변수를 선언해보자.

#include<stdio.h>

void main()
{
	int * arr1[5];
	int * arr2[3][5];

	? ? ? = arr1;
	? ? ? = arr2;
	......
}

 

답 :

int ** ptr1[5];
int* (*ptr2)[5];

 

 

문제2)
아래의 코드를 참조하여 ???을 대신할 수 있는 매개변수 선언을 추가해보자.

#include<stdio.h>

void SimpleFuncOne(? ? ? , ? ? ? ) { .... };
void SimpleFuncTwo(? ? ? , ? ? ? ) { .... };

void main()
{
	int arr1[3];
	int arr2[4];
	int arr3[3][4];
	int arr4[2][4];

	SimpleFuncOne(arr1, arr2);
	SimpleFuncTwo(arr3, arr4);
	.....
}

 

답 :

void SimpleFuncOne(int* ptr1, int* ptr2 ) { .... };
void SimpleFuncTwo(int (*ptr3)[4] , int (*ptr4)[4]) { .... };

 

 

문제3)
이 문제도 위의 문제와 유사하다. 즉 ??? 을 대신 할 수 있는 매개변수 선언을 추가하는 것이다. 그러나 이번에는 약간의 응용력을 요구한다.

#include<stdio.h>

void SimpleFuncOne(? ? ? , ? ? ? ) { .... };
void SimpleFuncTwo(? ? ? , ? ? ? ) { .... };

void main()
{
	int* arr1[3];
	int* arr2[3][5];
	int** arr3[5];
	int*** arr4[3][5];

	SimpleFuncOne(arr1, arr2);
	SimpleFuncTwo(arr3, arr4);

}

 

 

답 :

void SimpleFuncOne(int** ptr1, int* (*ptr2)[5] ) { .... };
void SimpleFuncTwo(int*** ptr3 , int*** (*ptr4)[5]) { .... };

 

 

문제4)
다음 예제의 출력 결과는 무엇인가? 이는 예제를 실행하지 않고 답을 해야 한다.

#include<stdio.h>

void main()
{
	int arr[3][2] = { {1,2},{3,4},{5,6} };
	printf("%d %d\n", arr[1][0], arr[0][1]);
	printf("%d %d\n", *(arr[2] + 1), *(arr[1] + 1));
	printf("%d %d\n", (*(arr + 2))[0], (*(arr + 0))[1]);
	printf("%d %d\n", **arr, *(*(arr + 0) + 0));
}

 

답 : 3, 2
      6, 4
      5, 2
      1, 1