10. 다차원 배열

header


1. 2차원 배열

2차원 배열은 행(row)과 열(column)로 구성된 평면 구조의 배열입니다.

2차원 배열의 개념

1차원 배열이 선형 구조라면, 2차원 배열은 표(table) 구조입니다.

실생활 예시:

  • 교실의 좌석 배치
  • 체스판
  • 엑셀 스프레드시트
int arr[3][4];  // 3행 4열의 2차원 배열

배열 구조 시각화:

  0열 1열 2열 3열
0행 arr[0][0] arr[0][1] arr[0][2] arr[0][3]
1행 arr[1][0] arr[1][1] arr[1][2] arr[1][3]
2행 arr[2][0] arr[2][1] arr[2][2] arr[2][3]
2차원 배열의 구조
• 첫 번째 인덱스: 행 번호 (세로)
• 두 번째 인덱스: 열 번호 (가로)
• 총 요소 개수 = 행 × 열

2차원 배열 선언

자료형 배열이름[행크기][열크기];

예시:

int scores[3][4];    // 3행 4열 (총 12개 요소)
double data[2][5];   // 2행 5열 (총 10개 요소)
char table[4][3];    // 4행 3열 (총 12개 요소)

2차원 배열의 메모리 크기

int arr[3][4];
  • int형: 4바이트
  • 요소 개수: 3 × 4 = 12개
  • 총 크기: 4 × 12 = 48바이트

실습 1

#include <stdio.h>

int main() {
    int arr[2][3];

    printf("배열 크기: %d바이트\n", sizeof(arr));
    printf("행 개수: %d\n", sizeof(arr) / sizeof(arr[0]));
    printf("열 개수: %d\n", sizeof(arr[0]) / sizeof(arr[0][0]));

    return 0;
}
실행 결과 보기
배열 크기: 24바이트
행 개수: 2
열 개수: 3
  • 총 크기: 2행 × 3열 × 4바이트(int) = 24바이트
  • 행 개수: 전체 크기 / 1행의 크기 = 24 / 12 = 2
  • 열 개수: 1행의 크기 / 1개 요소 크기 = 12 / 4 = 3

2. 2차원 배열의 초기화

2차원 배열은 여러 방법으로 초기화할 수 있습니다.

방법 1: 중괄호로 행 구분

int arr[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};
0열 1열 2열
0행 1 2 3
1행 4 5 6

방법 2: 일렬로 나열 (비권장)

int arr[2][3] = {1, 2, 3, 4, 5, 6};

순서대로 채워집니다. 하지만 가독성이 떨어지므로 방법 1을 권장합니다.

방법 3: 일부만 초기화

int arr[2][3] = {
    {1, 2},
    {4}
};
0열 1열 2열
0행 1 2 0
1행 4 0 0

나머지는 0으로 자동 초기화됩니다.

방법 4: 행 크기 생략

int arr[][3] = {
    {1, 2, 3},
    {4, 5, 6}
};
⚠️ 중요
• 행 크기는 생략 가능
열 크기는 반드시 명시해야 함

실습 2

#include <stdio.h>

int main() {
    int arr[3][2] = {
        {10, 20},
        {30, 40},
        {50, 60}
    };
    int i, j;

    printf("=== 2차원 배열 출력 ===\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 2; j++) {
            printf("arr[%d][%d] = %d\n", i, j, arr[i][j]);
        }
    }

    return 0;
}
실행 결과 보기
=== 2차원 배열 출력 ===
arr[0][0] = 10
arr[0][1] = 20
arr[1][0] = 30
arr[1][1] = 40
arr[2][0] = 50
arr[2][1] = 60

3. 2차원 배열과 반복문

2차원 배열은 중첩 for문을 사용하여 처리합니다.

기본 패턴

for (i = 0; i < 행크기; i++) {
    for (j = 0; j < 열크기; j++) {
        // arr[i][j] 처리
    }
}
  • 외부 루프: 행을 반복
  • 내부 루프: 열을 반복

실습 3 - 표 형태로 출력

#include <stdio.h>

int main() {
    int scores[3][4] = {
        {90, 85, 88, 92},
        {78, 95, 82, 88},
        {85, 90, 93, 87}
    };
    int i, j;

    printf("학생 | 국어 영어 수학 과학\n");
    printf("------|-------------------\n");

    for (i = 0; i < 3; i++) {
        printf(" %d번  |", i+1);
        for (j = 0; j < 4; j++) {
            printf(" %3d", scores[i][j]);
        }
        printf("\n");
    }

    return 0;
}
실행 결과 보기
학생 | 국어 영어 수학 과학
------|-------------------
 1번  |  90  85  88  92
 2번  |  78  95  82  88
 3번  |  85  90  93  87

실습 4 - 학생별 평균 계산

#include <stdio.h>

int main() {
    int scores[3][4] = {
        {90, 85, 88, 92},
        {78, 95, 82, 88},
        {85, 90, 93, 87}
    };
    int i, j;
    double sum, average;

    for (i = 0; i < 3; i++) {
        sum = 0;
        for (j = 0; j < 4; j++) {
            sum += scores[i][j];
        }
        average = sum / 4;
        printf("학생 %d 평균: %.2f\n", i+1, average);
    }

    return 0;
}
실행 결과 보기
학생 1 평균: 88.75
학생 2 평균: 85.75
학생 3 평균: 88.75

4. 3차원 배열

3차원 배열은 높이(depth), 행, 열의 3차원 구조를 가집니다.

3차원 배열의 개념

int arr[2][3][4];
  • 높이(depth): 2 (2개의 2차원 배열)
  • 행(row): 3
  • 열(column): 4
  • 총 요소: 2 × 3 × 4 = 24개

3차원 배열 시각화:

[0층]               [1층]
┌─────────┐        ┌─────────┐
│ 3 x 4   │        │ 3 x 4   │
│ 배열    │        │ 배열    │
└─────────┘        └─────────┘
💡 3차원 배열 이해하기
3차원 배열은 "2차원 배열을 여러 개 쌓아놓은 구조"로 생각하면 쉽습니다.

3차원 배열 선언과 초기화

int arr[2][3][4] = {
    {   // 0층
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    },
    {   // 1층
        {13, 14, 15, 16},
        {17, 18, 19, 20},
        {21, 22, 23, 24}
    }
};

3차원 배열 접근

arr[0][1][2] = 7;   // 0층, 1행, 2열
arr[1][2][3] = 24;  // 1층, 2행, 3열

실습 5

#include <stdio.h>

int main() {
    int arr[2][2][3] = {
        {
            {1, 2, 3},
            {4, 5, 6}
        },
        {
            {7, 8, 9},
            {10, 11, 12}
        }
    };
    int i, j, k;

    printf("=== 3차원 배열 출력 ===\n");
    for (i = 0; i < 2; i++) {
        printf("[%d층]\n", i);
        for (j = 0; j < 2; j++) {
            for (k = 0; k < 3; k++) {
                printf("%3d ", arr[i][j][k]);
            }
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}
실행 결과 보기
=== 3차원 배열 출력 ===
[0층]
  1   2   3
  4   5   6

[1층]
  7   8   9
 10  11  12

3차원 배열의 메모리 크기

#include <stdio.h>

int main() {
    int arr[2][3][4];

    printf("전체 크기: %d바이트\n", sizeof(arr));
    printf("층 개수: %d\n", sizeof(arr) / sizeof(arr[0]));
    printf("행 개수: %d\n", sizeof(arr[0]) / sizeof(arr[0][0]));
    printf("열 개수: %d\n", sizeof(arr[0][0]) / sizeof(arr[0][0][0]));

    return 0;
}
실행 결과 보기
전체 크기: 96바이트
층 개수: 2
행 개수: 3
열 개수: 4

2 × 3 × 4 × 4바이트(int) = 96바이트


5. 배열 포인터

배열 포인터는 배열 전체를 가리키는 포인터입니다.

포인터 배열 vs 배열 포인터

두 개념을 혼동하지 마세요!

포인터 배열:

int *arr[3];  // int형 포인터 3개를 가지는 배열

배열 포인터:

int (*ptr)[3];  // int형 배열(크기 3)을 가리키는 포인터
구분 방법
int *arr[3] → 배열이 먼저 (포인터 배열)
int (*ptr)[3] → 괄호로 포인터가 먼저 (배열 포인터)

배열 포인터의 사용

배열 포인터는 2차원 배열을 가리킬 때 주로 사용합니다.

int arr[2][3] = {
    {1, 2, 3},
    {4, 5, 6}
};

int (*ptr)[3];  // 크기 3인 int 배열을 가리키는 포인터
ptr = arr;      // arr의 첫 번째 행을 가리킴

실습 6

#include <stdio.h>

int main() {
    int arr[2][3] = {
        {10, 20, 30},
        {40, 50, 60}
    };

    int (*ptr)[3];  // 배열 포인터 선언
    ptr = arr;      // arr의 첫 번째 행을 가리킴
    int i, j;

    printf("=== 배열 포인터로 접근 ===\n");
    for (i = 0; i < 2; i++) {
        for (j = 0; j < 3; j++) {
            printf("%d ", ptr[i][j]);
        }
        printf("\n");
    }

    return 0;
}
실행 결과 보기
=== 배열 포인터로 접근 ===
10 20 30
40 50 60

배열 포인터의 연산

int arr[3][4];
int (*ptr)[4] = arr;

ptr;      // arr[0]을 가리킴 (0행)
ptr + 1;  // arr[1]을 가리킴 (1행)
ptr + 2;  // arr[2]를 가리킴 (2행)

배열 포인터를 1 증가시키면 다음 행을 가리킵니다.


6. 종합 실습

문제 1 - 2차원 배열 크기 (기초)

문제 1

int arr[4][5]의 전체 크기는 몇 바이트입니까?

다차원 배열

문제 2 - 2차원 배열 접근 (기초)

문제 2

다음 코드의 실행 결과는?

다차원 배열
#include <stdio.h>

int main() {
    int arr[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };

    printf("%d", arr[1][2]);

    return 0;
}

문제 3 - 2차원 배열 초기화 (기초)

문제 3

다음 코드의 실행 결과는?

다차원 배열
#include <stdio.h>

int main() {
    int arr[2][3] = {
        {10, 20},
        {30}
    };

    printf("%d", arr[0][2] + arr[1][1]);

    return 0;
}

문제 4 - 2차원 배열 합계 (중급)

문제 4

다음 코드의 실행 결과는?

다차원 배열
#include <stdio.h>

int main() {
    int arr[2][2] = {
        {5, 10},
        {15, 20}
    };
    int i, j, sum = 0;

    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) {
            sum += arr[i][j];
        }
    }

    printf("%d", sum);

    return 0;
}

문제 5 - 3차원 배열 (중급)

문제 5

다음 코드의 실행 결과는?

다차원 배열
#include <stdio.h>

int main() {
    int arr[2][2][2] = {
        {{1, 2}, {3, 4}},
        {{5, 6}, {7, 8}}
    };

    printf("%d", arr[1][0][1] + arr[0][1][1]);

    return 0;
}

문제 6 - 대각선 합 (고급)

문제 6

다음 코드에서 3×3 배열의 대각선 합은?

다차원 배열
#include <stdio.h>

int main() {
    int arr[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    int i, sum = 0;

    for (i = 0; i < 3; i++) {
        sum += arr[i][i];
    }

    printf("%d", sum);

    return 0;
}

핵심 요약

1. 2차원 배열
• 선언: int arr[행][열];
• 행과 열로 구성된 표 구조
• 접근: arr[i][j]
• 초기화: 중괄호로 행 구분

2. 2차원 배열 순회
• 중첩 for문 사용
• 외부 루프: 행 반복
• 내부 루프: 열 반복

3. 3차원 배열
• 선언: int arr[높이][행][열];
• 2차원 배열을 쌓아놓은 구조
• 3중 중첩 for문으로 순회

4. 배열 포인터
• 선언: int (*ptr)[열크기];
• 배열 전체를 가리키는 포인터
• 2차원 배열 접근에 활용
• 포인터 배열과 구분 필수

5. 메모리 크기
• 2차원: 행 × 열 × 자료형 크기
• 3차원: 높이 × 행 × 열 × 자료형 크기
sizeof()로 계산 가능