다차원 배열을 학습하기 전에, 배열에 종류에 대해 간단히 살펴보고 넘어가겠습니다.
배열의 종류
static 배열
index의 최대 범위가 compile시에 결정되는 배열로써, 메모리도 compile시에 할당됩니다.
C언어의 전역 배열 변수 int arr[] = {1,2,3} 등이 포함됩니다.
Fixed Dynamic 배열
index의 최대 범위가 compile시에 결정되지만, 메모리는 실행 중 함수가 호출될 때 할당되는 배열입니다.
C의 지역 배열 변수의 경우 Stack에 할당됩니다. (예: int arr[10];)
그러나 자바의 경우에는 Heap 영역에 할당됩니다.
(Non - Fixed) Dynamic 배열
최대 index를 실행시키기 전에는 모릅니다. 메모리도 실행될 때 할당됩니다.
자바의 ArrayList 등이 이에 포함됩니다.
배열 관리 방법
Descriptor를 사용하여 관리합니다.
Descriptor는 메모리를 할당하는 코드를 생성합니다.
Compile Descriptor
컴파일 시 다음과 같은 정보를 가집니다.
- 원소 타입
- Index의 상한
- 시작 주소 관련된 정보
- (배열의 차원 수) - 다차원 배열부터
다른 언어는 다를 수 있으며, 이는 C언어 기준입니다.
Runtime Descriptor
C언어는 런타임에는 Descriptor를 가지지 않습니다.
그러나 Java에서는 실행 중에도 Descriptor를 가지며 이로 인해 ArrayIndexOutOfBoundException등을 발생시킵니다.
Runtime Descriptor를 가지면 실행속도는 좀 더 느려진다는 단점이 있으나, 안전하다는 장점이 있습니다.
다차원 배열의 저장
C언어에서는 Rectangle(정방형) 배열을 지원합니다.
C언어의 경우, 배열은 같은 타입의 여러 요소들을 연속된 메모리에 할당합니다.
그리고 원소를 저장하는 경우 행-우선 방법으로 저장합니다.
Rectangle 배열
모든 행이 동일 개수의 요소들을 포함하며, 모든 열이 동일 개수의 요소들을 포함합니다.
(이는 Square 배열이 아니며, 따라서 행과 열의 수는 같지 않을 수 있습니다.)
다차원 배열의 크기
sizeof(자료형 arr[A][B][C]) 는 sizeof(자료형)$\cdot$ A $\cdot$ B $\cdot$ C 와 동일합니다.
printf("%lu\n", sizeof(int[2][3][4][5]));//480
printf("%lu\n", sizeof(int)*2*3*4*5);//480
2차원 배열의 요소 주소 구하기
1차원 배열의 경우 요소의 주소와 값은 다음과 같이 구했습니다.
int arr[10];
0번째 요소의 주소 : arr 또는 &arr[0]
0번째 요소의 값 : *arr 또는 arr[0]
1번째 요소의 주소 : arr+1 또는 &arr[1]
1번째 요소의 값 : *(arr+1) 또는 arr[1]
2번째 요소의 주소 : arr+2 또는 &arr[2]
2번째 요소의 값 : *(arr+2) 또는 arr[2]
2차원 배열의 경우에는 다음과 같습니다.
int arr[2][3];
0,0번째 요소의 주소 : arr 또는 &arr[0] 또는 &arr[0][0]
0,0번째 요소의 값 : **(arr) 또는 arr[0][0]
0,1번째 요소의 주소 : (*arr) + 1 또는 &arr[0][1]
0,1번째 요소의 값 : *( *(arr)+1 ) 또는 arr[0][1]
0,2번째 요소의 주소 : (*arr) + 2 또는 &arr[0][2]
0,2번째 요소의 값 : *( *(arr)+2 ) 또는 arr[0][2]
1,0번째 요소의 주소 : arr + 1 또는 &arr[1][0] 또는 (*arr) + 3 또는 arr[1]
1,0번째 요소의 값 : **(arr + 1) 또는 *(*(arr) +3 ) 또는 arr[1][0]
1,1번째 요소의 주소 : (*(arr + 1) + 1) 또는 &arr[1][1]
1,1번째 요소의 값 : *(*(arr + 1)+1) 또는 arr[1][0]
컴퓨터에게 시키지 않고 직접 계산하는 방법은 다음과 같습니다.
자료형 arr[A][B];
arr[i][j]의 주소 : arr(시작주소) + ( (i $\cdot$ B + j) $\cdot$ sizeof(자료형) )
다차원 배열의 초기화
중요한 점은 배열 선언에서 맨 처음 하나만 생략할 수 있다는 것입니다.
int arr[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
int arr[3][3] = {{1}, {4,5}, {7,8,9}}; //빈 곳은 0으로
int arr[3][3] = {1,2,3,4,5,6,7}; //빈 곳은 0으로, {{1,2,3}, {4,5,6}, {7}};과 동일
//int arr[][] = {1,2,3,4,5,6,7,8} - 오류 발생! 8x1? 4x2? 2x4???
//세로길이만 생략 가능하다.
int arr1[][4] = {1,2,3,4,5,6,7,8}; //컴파일러가 arr[2][4]라고 계산함
int arr2[][2] = {1,2,3,4,5,6,7,8}; //컴파일러가 arr[4][2]라고 계산함
// int matrix[][3][4] = ~~~~ - 가능!
// int matrix[][3][4] = ~~~~ - 불가능!
// int matrix[3][][4] = ~~~~ - 불가능!
'c언어' 카테고리의 다른 글
[C언어] - 동적 메모리 할당 (malloc) (0) | 2022.06.12 |
---|---|
[C언어] - 이중 포인터 (0) | 2022.05.06 |
[C언어] - Const (0) | 2022.04.20 |
[C언어] - Call By Value (0) | 2022.04.20 |
[C언어] - 포인터 (0) | 2022.04.19 |