https://codejin.tistory.com/48
계속해서 이어가자.
2차원 배열 arr에서 arr와 arr[0]은 같은 위치를 가르키는 다른 변수라고 했다.
계속해서 2차운 배열의 형이 무엇인지 알아가보자.
포인터 연산 - 배열이름에 1을 더해보자
TYPE형 1차원 배열이름에 1을 더하면 sizeof(TYPE)만큼 증가하였다. 이를 역으로 이용하면 어떤 1차원 배열의 값에 1을 더했을때 sizeof(TYPE)만큼 증가했다면, 그 배열은 TYPE형인 것을 유추할 수 있을 것이다. 그러면 이를 2차원 배열에도 이용을 한번 해보자.
다음 예제를 보자.
#include <stdio.h>
int main () {
int arr_1[2][3];
int arr_2[3][4];
printf("arr_1 : %p \n", arr_1);
printf("arr_1 + 1 : %p \n", arr_1 + 1);
printf("arr_1 + 2 : %p \n\n", arr_1 + 2);
printf("arr_2 : %p \n", arr_2);
printf("arr_2 + 1 : %p \n", arr_2 + 1);
printf("arr_2 + 2 : %p \n", arr_2 + 2);
printf("arr_2 + 3 : %p \n", arr_2 + 3);
return 0;
}
실행결과
arr_1 : 0061FF08
arr_1 + 1 : 0061FF14
arr_1 + 2 : 0061FF20
arr_2 : 0061FED8
arr_2 + 1 : 0061FEE8
arr_2 + 2 : 0061FEF8
arr_2 + 3 : 0061FF08
자세히 살펴보면 arr_1에는 1을 더할때마다 12만큼 증가하고, arr_2는 16만큼 증가하는 것을 볼 수 있다. sizeof(int)는 4이므로 2차원배열에 1을 더하면 (그 배열의 행의 길이) x (sizeof(TYPE))만큼 증가하는 것이다. 이는 다음 행의 첫번째 요소의 첫번째 값을 가르키는 뜻이다.
그런데 뭔가 이상하다. 같은 int형 2차원 배열인데도 변하는 값이 다르다. 그러면 둘이 다른 포인터 형이라는 것인가? 단지 행의 길이가 다르다는거 하나만으로?
정답이다. 이러한 이유로 인해 2차원 배열의 포인터 형을 결정하기 어려운 것이다.
결론 : 2차원 배열이름의 표인터 형
일단 우리는 지금까지의 예제를 통해 2차원 포인터가 가져야 할 정보를 취합하면 다음과 같을 것이다.
-가르키는 대상의 자료형은 무엇인가?
-배열이름을 대상으로 증감연산을 시행하면 실제로 변화하는 값은 얼마인가?
그러면 2차원 배열이름의 포인터형을 묻는다면 어떻게 답해야 할까? 다음 배열을 예시로 한번 설명해보자
int arr[3][4];
배열이름 arr는 int형 변수를 가르키고 포인터 증감연산시 sizeof(int) x 4만큼 변하는 포인터형이다.
그러면 뭐 딱 떨어지게 하는 단어가 없는건가? 없다. 애초에 행의 길이만으로 형이 바뀌어 버리는데 어떻게 딱 떨어지게 정리를 하겠는가.
포인터 변수 선언을 통한 2차원 배열 선언
배열은 곧 포인터이니 포인터 변수로도 2차원배열의 선언이 가능할 것이다. 어떻게 해야할까?
예를 들어 우리가 int형 변수를 가르키고 포인터 연산시 sizeof(int) x 4만큼 변하는 포인터 변수를 선언하려면 다음과 같이 선언하면 된다.
int (*ptr)[4];
이건 뭐 포인터 변수를 선언한건지 배열을 선언한건지 구분이 안간다. 하지만 이것은 확실한 포인터 변수이다. ptr이라는 이름의 포인터 변수를 선언한 것이며, int는 가르키는 대상의 자료형, [4]는 한번에 건너뛸 변수의 개수이다. 여기서는 int형이니 1을 더하면 int형 변수를 4개만큼 건너뛰겠다는 의미이다.
이를 정리하면 TYPE형 변수를 가르키고 포인터 연산시 sizeof(TYPE) x N만큼 증가하는 포인터 변수 var는 다음과 같을 것이다.
TYPE (*var)[N];
포인터 배열과 유사하게 생겼지만 절대 혼동하지 말자.
2차원 배열을 함수의 인자로 전달하기
1차원 배열을 인자로 받을때는 포인터 변수와 배열, 이 두가지 방법을 사용했었다.
TYPE func_1(another_TYPE * arr);
TYPE func_2(another_TYPE arr[]);
2차원 배열도 마찬가지로 포인터 변수와 배열을 통해 전달하면 된다.
TYPE func_1(another_TYPE (*arr)[]);
TYPE func_2(another_TYPE arr[][]);
하지만 이렇게 작성하면 함수 안에서 이 배열을 어떻게 나눠야 할지 모르기 때문에 가로, 세로값 둘중 적어도 하나는 넘겨줘야 한다. 따라서 다음과 같이 적는 것이 적절하다.
TYPE func_1(another_TYPE (*arr)[N]);
TYPE func_2(another_TYPE arr[N][]);
TYPE func_3(another_TYPE arr[][N]);
2차원 배열에서의 arr[i] == *(arr+i)
포인터와 배열의 관계에서 우리는 위의 식을 배웠다. 이 식은 다차원 배열에서도 성립하는데, 간단한 치환이니 겁먹지는 말자.
inr arr[3][3];
//arr[2][1]의 값을 4로 바꾸고자 한다.
arr[2][1] = 4; // 여기서부터 6번째 줄까지 모두 같은 뜻
*(arr[2]+1) = 4; // 1
(*(arr+2))[1] = 4; // 2
*(*(arr+2)+1)) = 4; // 3
1dml ruddn arr[2]를 하나의 배열로 보고 바꾼 것이고, 2의 경우는 arr[2]를 위의 식으로 바꾼것이며, 3은 이걸 다 합친 것이다. 이런식으로 위의 식은 다차원 배열에서도 성립한다.
'Language > C' 카테고리의 다른 글
포인터(完) - 연습문제 풀이 (0) | 2021.09.08 |
---|---|
포인터(9) (0) | 2021.09.06 |
포인터(8) - 上 (0) | 2021.09.04 |
포인터 (7) + 간단한 문제풀이 (0) | 2021.09.02 |
포인터(6.5) (0) | 2021.09.01 |