2023.1.9. 최초 작성
2023.1.11. 내용 추가
2023.1.16 내용 추가
1차원 배열은 번지가 1개이고 2차원 배열은 번지가 2개이다.
아래 코드는 2차원 배열의 구조를 확인하기 위한 예제이다.
#include <stdio.h>
void main() {
int arr1[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 배열 접근 방식
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("arr1[%d][%d] address : %p, ", i, j, &arr1[i][j]);
printf("arr1[%d][%d] value : %d\n", i, j, arr1[i][j]);
}
}
puts("============================================================");
// 배열 + 포인터 접근 방식
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("arr1[%d]+%d address : %p, ", i, j, arr1[i]+j);
printf("arr1[%d]+%d value : %d\n", i, j, *(arr1[i]+j));
}
}
puts("============================================================");
// 포인터 접근방식
for (int i = 0; i < 12; i++) {
printf("(*arr1)+%d address : %p, ", i, (*arr1)+i);
printf("(*arr1)+%d value : %d\n", i, *((*arr1)+i));
}
}
[실행 결과]
arr1[0][0] address : 0000004AEF3FFA38, arr1[0][0] value : 1
arr1[0][1] address : 0000004AEF3FFA3C, arr1[0][1] value : 2
arr1[0][2] address : 0000004AEF3FFA40, arr1[0][2] value : 3
arr1[0][3] address : 0000004AEF3FFA44, arr1[0][3] value : 4
arr1[1][0] address : 0000004AEF3FFA48, arr1[1][0] value : 5
arr1[1][1] address : 0000004AEF3FFA4C, arr1[1][1] value : 6
arr1[1][2] address : 0000004AEF3FFA50, arr1[1][2] value : 7
arr1[1][3] address : 0000004AEF3FFA54, arr1[1][3] value : 8
arr1[2][0] address : 0000004AEF3FFA58, arr1[2][0] value : 9
arr1[2][1] address : 0000004AEF3FFA5C, arr1[2][1] value : 10
arr1[2][2] address : 0000004AEF3FFA60, arr1[2][2] value : 11
arr1[2][3] address : 0000004AEF3FFA64, arr1[2][3] value : 12
============================================================
arr1[0]+0 address : 0000004AEF3FFA38, arr1[0]+0 value : 1
arr1[0]+1 address : 0000004AEF3FFA3C, arr1[0]+1 value : 2
arr1[0]+2 address : 0000004AEF3FFA40, arr1[0]+2 value : 3
arr1[0]+3 address : 0000004AEF3FFA44, arr1[0]+3 value : 4
arr1[1]+0 address : 0000004AEF3FFA48, arr1[1]+0 value : 5
arr1[1]+1 address : 0000004AEF3FFA4C, arr1[1]+1 value : 6
arr1[1]+2 address : 0000004AEF3FFA50, arr1[1]+2 value : 7
arr1[1]+3 address : 0000004AEF3FFA54, arr1[1]+3 value : 8
arr1[2]+0 address : 0000004AEF3FFA58, arr1[2]+0 value : 9
arr1[2]+1 address : 0000004AEF3FFA5C, arr1[2]+1 value : 10
arr1[2]+2 address : 0000004AEF3FFA60, arr1[2]+2 value : 11
arr1[2]+3 address : 0000004AEF3FFA64, arr1[2]+3 value : 12
============================================================
(*arr1)+0 address : 0000004AEF3FFA38, (*arr1)+0 value : 1
(*arr1)+1 address : 0000004AEF3FFA3C, (*arr1)+1 value : 2
(*arr1)+2 address : 0000004AEF3FFA40, (*arr1)+2 value : 3
(*arr1)+3 address : 0000004AEF3FFA44, (*arr1)+3 value : 4
(*arr1)+4 address : 0000004AEF3FFA48, (*arr1)+4 value : 5
(*arr1)+5 address : 0000004AEF3FFA4C, (*arr1)+5 value : 6
(*arr1)+6 address : 0000004AEF3FFA50, (*arr1)+6 value : 7
(*arr1)+7 address : 0000004AEF3FFA54, (*arr1)+7 value : 8
(*arr1)+8 address : 0000004AEF3FFA58, (*arr1)+8 value : 9
(*arr1)+9 address : 0000004AEF3FFA5C, (*arr1)+9 value : 10
(*arr1)+10 address : 0000004AEF3FFA60, (*arr1)+10 value : 11
(*arr1)+11 address : 0000004AEF3FFA64, (*arr1)+11 value : 12
주소의 간격이 모두 int 크기만큼 차이가 나는 것이 확인된다.
3가지 방법으로 출력하였는데 모두 2차원 배열에 접근하는 방식이다.
첫 번째 방식은 배열 접근 방식만 사용한 것이다.
두 번째 방식은 배열 접근 방식과 포인터 접근 방식을 같이 사용한 것으로 하이브리드다.
세 번째 방식은 포인터 접근 방식만 사용한 것이다.
정수 타입의 2차원 배열을 그림으로 그리면 아래와 같다.

2차원 배열의 이름인 arr1은 배열의 맨 처음 주소이다. arr1에 1을 더하면 주소는 16byte 증가한다. 1차원 배열에서는 배열의 자료형 크기만큼 증가하기 때문에 int 타입의 크기인 4byte 증가를 확인하였는데 2차원 배열에서는 4byte의 4배인 16byte가 증가하게 된다.
그 이유는 아래의 배열 구조 때문이다.
int arr1[3][4] = {
{1, 2, 3, 4}, // arr1[0]
{5, 6, 7, 8}, // arr1[1]
{9, 10, 11, 12} // arr1[2]
};
2차원 배열에서 배열의 이름인 arr1을 해석해보면 1차원 배열 arr1[4] 타입의 배열의 3개 있다는 의미로 볼 수 있다.
arr1[3][4]
빨간색이 자료형이고 파란색이 배열의 개수라고 생각하면 된다.
2차원 배열에서 첫 번째 대괄호의 숫자는 행의 개수인데 아래로 증가한다. 두 번째 대괄호의 숫자는 열의 개수인데 오른쪽으로 증가한다.
2차원 배열은 1차원 배열이 3개 있는 것이다.
2차원 배열을 1차원 배열처럼 생각하면 int 4개짜리 배열이 하나의 자료형이 되는 것이다.
2차원 배열은 실제로 1차원 배열로 메모리에 기억된다.

int 4개짜리 배열이 아닌 int 1개의 크기만큼 주소를 증가시키고 싶으면 다음과 같이 *연산자를 이용한다.
(*arr1) + 1
arr1 일 때는 int 4개짜리 배열 크기만큼 증가하게 되지만 앞에 간접 참조 연산자인 *을 붙이면 int 타입의 크기만큼 증가시킬 수 있다.
정리하면 int 타입의 2차원 배열에서 arr1 + 1 은 int[]의 크기만큼 증가, (*arr1) + 1은 int의 크기만큼 증가하게 된다.
2차원 배열도 내부적으로는 1차원 배열로 기억되므로 arr1[0][1]과 같이 대괄호를 2개 사용하였을 때 arr1[0]타입의 1차원 배열 1번지라고 생각하면 된다.
'프로그래밍 > C' 카테고리의 다른 글
CONST를 이용한 상수화 (1) | 2023.01.16 |
---|---|
C언어 포인터 변수 (0) | 2023.01.16 |
배열의 이름은 주소이다. (0) | 2023.01.09 |
static 변수와 static 함수 (0) | 2023.01.09 |
C언어 함수 (0) | 2023.01.08 |