다차원 배열 : 2차원 이상의 배열
2차원, 3차원 배열? OK! 4차원, 5차원 배열? NO!
2차원 배열 : 평면 구조
3차원 배열 : 직육면체 구조
4차원, 5차원 : ....
1차원 배열
길이가 10인 1차원 int형 배열
int arronedim[10];
2차원 배열
가로, 세로의 길이가 5인 2차원 int형 배열
int arrtwodim[5][5];
3차원 배열
가로, 세로, 높이의 길이가 3인 3차원 int형 배열
int arrthreedim[3][3][3];
다차원 배열을 대표하는 2차원 배열의 선언
int arr1[3][4]; // 세로가 3, 가로가 4인 int형 2차원 배열
int arr2[2][6]; // 세로가 2, 가로가 6인 int형 2차원 배열
배열요소 안에 삽입된 두 개의 숫자는 각각의 요소에 접근할 때 사용하게 되는 인덱스 값
배열 이름이 arr이고 배열요소의 자료형이 TYPE이라 할 때, 2차원 배열의 선언형태는 다음과 같다
TYPE arr[세로길이][가로길이];
2차원 배열의 크기
#include <stdio.h>
int main(void)
{
int arr1[3][4];
int arr2[7][9];
printf("세로3, 가로4: %d \n", sizeof(arr1));
printf("세로7, 가로9: %d \n", sizeof(arr2));
}
3(세로) x 4(가로) x int 4 = 48 바이트
7(세로) x 9(가로) x int 4 = 252 바이트
2차원 배열요소의 접근
int arr[3][3];
0으로 초기화 되었다고 가정
이 문장이 실행되면
arr[0][0]=1;
다음 문장이 실행되면
arr[0][1]=2;
arr[2][1]=5;
이름이 arr인 int형 배열을 대상으로 세로 N번째 위치(1부터 시작해서 N번째), 그리고 가로 M번째 위치(1부터 시작해서 M번째)에 저장된 값을 변경 및 참조하는 방법
arr[N-1][M-1] = 20; // 세로 N, 가로 M의 위치에 정수 20을 저장
printf("%d", arr[N-1][M-1]) // 세로 N, 가로 M의 위치에 저장된 값 출력
층별로 두 가구가 사는 4층짜리 빌라의 가구별 거주인원 수 예시
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void)
{
int villa[4][2];
int popu;
/* 가구별 거주인원 입력 받기 */
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%d층 %d호 인구수 : ", i + 1, j + 1);
scanf("%d", &villa[i][j]);
}
}
/* 빌라의 층별 인구수 출력하기*/
for (int i = 0; i < 4; i++)
{
popu = 0;
for (int j = 0; j < 2; j++)
{
popu += villa[i][j];
}
printf("%d층 인구수 : %d \n", i + 1, popu);
}
}
- 위 예제는 1차원 배열로도 구현이 가능
- 그러나 이는 프로그램을 복잡하게 만들뿐임
- 2차원적 모델의 문제를 해결하기 위해서는 2차원 배열을 선언하는 것이 바람직
2차원 배열의 메모리상 할당의 형태
2차원 배열은 물리적으로도 2차원 형태로 존재?
- 우리가 사용하는 메모리의 주소 값은 다음과 같이 1차원적 구조.
- 0x1001번지, 0x1001번지, 0x1003번지, 0x1004번지, 0x1005번지....
2차원적 구조였다면 메모리의 주소 값은 다음의 형태
- 0x12-0x24번지, 0x12-0x25번지, 0x12-0x26번지, 0x12-0x27번지......
- 0x13-0x24번지, 0x13-0x25번지, 0x13-0x26번지, 0x13-0x27번지......
- 0x14-0x24번지, 0x14-0x25번지, 0x14-0x26번지, 0x14-0x27번지......
따라서 2차원 배열도 메모리상에는 1차원의 형태로 존재.
세로 길이가 3이고 가로 길이가 2인 int형 배열을 선언하면 다음과 같은 구조로 메모리상에 존재
실제로 위 그림의 형태로 배열이 할당되는지 확인. 2차원 배열요소의 주소 값을 출력
#include <stdio.h>
int main(void)
{
int arr[3][2];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
printf("%p\n", &arr[i][j]);
}
}
}
2차원 배열 선언과 동시에 초기화
2차원 배열도 선언과 동시에 초기화 가능
가장 일반적인 초기화 방법
#include <stdio.h>
int main(void)
{
int arr[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
}
행 단위로 초기화할 값들을 별도의 중괄호로 명시해야 한다.
물론 모든 배열요소를 초기화해야 하는 것은 아니다.
일부 요소에 대해서는 초기화를 생략할 수 있다.
이렇게 해서 비게 되는 공간은 1차원 배열과 마찬가지로 0으로 초기화된다.
#include <stdio.h>
int main(void)
{
int arr[3][3] = {
{1},
{4, 5},
{7, 8, 9}
};
printf("%d\n", arr[0][1]);
}
위 초기화는 아래와 같음
#include <stdio.h>
int main(void)
{
int arr[3][3] = {
{1, 0, 0},
{4, 5, 0},
{7, 8, 9}
};
printf("%d\n", arr[0][1]);
}
초기화 했을 때 부족한 영역은 0으로 초기화된다.
한줄에 선언하는 것도 가능
int arr[3][3] = {1, 2, 3, 4, 5, 6, 7};
다음의 배열선언과 동일한 결과로 이어짐
int arr[3][3] = {1, 2, 3, 4, 5, 6, 7, 0, 0};
초기화 관련내용 확인 예제
#include <stdio.h>
int main(void)
{
/* 2차원 배열 초기화의 예 1*/
int arr1[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
/* 2차원 배열 초기화의 예 2*/
int arr2[3][3] = {
{1},
{4, 5},
{7, 8, 9}
};
/* 2차원 배열 초기화의 예 3*/
int arr3[3][3] = {1, 2, 3, 4, 5, 6, 7};
/* 출력 1 */
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
printf("%d ", arr1[i][j]);
printf("\n");
}
printf("\n");
/* 출력 2 */
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
printf("%d ", arr2[i][j]);
printf("\n");
}
printf("\n");
/* 출력 3 */
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
printf("%d ", arr3[i][j]);
printf("\n");
}
printf("\n");
}
배열의 크기를 알려주지 않고 초기화하기
1차원 배열선언 시, 초기화 리스트가 존재한다면, 배열의 길이를 명시하지 않아도 됐음
2차원 배열도 마찬가지.
2차원 배열도 초기화 리스트가 존재한다면, 그 길이를 명시하지 않아도 된다.
단, 제약사항이 있다.
int arr[][] = {1, 2, 3, 4, 5, 6, 7, 8};
위 문장을 본다면 배열의 가로와 세로의 길이를 어떻게 결정?
여기에는 여러 가지의 경우의 수가 존재
(2 x 4도 되고 4 x 2도 됨)
(1 x 8도 되고 8 x 1도 됨)
따라서 컴파일러는 "하나는 가르쳐줘야 된다" 라고 한다
int arr1[][4] = {1, 2, 3, 4, 5, 6, 7, 8};
int arr2[][2] = {1, 2, 3, 4, 5, 6, 7, 8};
위와 같이 설정하면 된다
arr1의 경우 가로의 길이가 4이니, 세로의 길이는 2가 될 것이고
arr2의 경우 가로의 길이가 2이니, 세로의 길이는 4가 될 것이다.
"2차원 배열을 선언과 동시에 초기화하는 경우에는 배열의 세로길이만 생략이 가능하다."
참고 : [윤성우 열혈 C 프로그래밍] - 대부분의 내용 및 코드는 이 책에서 개인 공부 정리 목적으로 참고하였습니다.
'Language&Framework&Etc > C' 카테고리의 다른 글
포인터의 포인터(17-1) 포인터의 포인터에 대한 이해 (0) | 2020.12.09 |
---|---|
다차원 배열(16-2) 3차원 배열 (0) | 2020.12.09 |
포인터와 함수에 대한 이해(14-3) 포인터 대상의 const 선언 (0) | 2020.12.08 |
포인터와 함수에 대한 이해(14-2) Call-by-value vs Call-by-reference (0) | 2020.12.08 |
포인터와 함수에 대한 이해(14-1) 함수의 인자로 배열 전달하기 (0) | 2020.12.08 |