독서/C Programming : A Modern Approach

[KNK] chapter 8 : 배열

도리언 옐로우 2024. 9. 9. 17:05

1. 1차원 배열

배열은 특정 개수의 원소들을 연속적으로 저장하는 자료구조이다. 파이썬의 리스트와 달리 C언어의 배열은 원소들이 같은 형을 가져야 한다. 이는 C언어에서의 배열은 메모리에서 연속적으로 할당되기 때문이다.

https://learningc.org/chapters/chapter07-arrays/what-are-arrays

그렇다면 C언어에서 배열을 선언할 때에 우선적으로 배열 원소의 형과 크기를 결정해주어야 한다는 점을 자연스럽게 이해할 수 있다.

 

C언어에서는 배열에서 첨자의 범위를 확인하는 기능을 강제하지 않는다고 한다. 파이썬에서 배열의 범위를 벗어나는 경우 오류를 발생시키는 것과 달리, C에서 배열의 범위를 벗어나게 되면 어떤 예상할 수 없는 값을 출력될 수 있다는 것이다. 실제로 온라인 C 컴파일러로 아래의 코드를 실행시켜 보면 이상한 값이 출력되는 것을 확인할 수 있다.

#include <stdio.h>

int main() {
    int a[3] = {1, 2, 3};
    printf("%d", a[3]);
    return 0;
}

// OUTPUT : 10396928 !?

 

배열은 선언과 함께 초기화 할 수 있다. 바로 위 코드에서도 중괄호를 활용하여 배열 a를 초기화시킨 모습을 확인할 수 있다. 이는 파이썬의 리스트가 대괄호를 이용한다는 것과 구별된다. 이외에 초기화 관련하여 기억하면 좋을 사항들을 정리해 본다.

  • 만약 array initializer가 배열보다 짧은 int a[3] = {1, 2}; 와 같은 경우에는 나머지 원소들은 0이라는 값을 갖게 된다.
  • 위와 달리 중간 위치의 원소에 값을 넣어주고 나머지는 기본값으로 초기화하고 싶은 경우가 있을 수 있는데, C99의 designated initializer가 이를 가능케 한다. 예를 들어 int a[3] = {[2] = 3, [0] = 1}; 과 같이 작성한다면 배열 a는 {1, 0, 3}으로 초기화된다.
  • 또한 array initializer가 존재한다면 배열의 길이를 굳이 적을 필요가 없이 int a[] = {1,2,3};처럼 작성할 수 있다.
  • 만약 designated initializer 방식으로 초기화 하는 경우에는 가장 큰 지정자의 값을 통해 배열의 길이를 추론하게 된다. 예를 들어 int a[] = {[2] = 3, [0] = 1}; 의 경우 가장 큰 지정자가 2이므로 배열의 크기가 3임을 추론한다는 것이다.

2. 다차원 배열

C언어에서는 포인터의 배열을 통해 다차원 자료를 좀더 유연하게 저장할 수 있기 때문에 다차원 배열의 중요도가 다른 언어에 비해 상대적으로 떨어진다고 한다. 여기서는 C언어의 다차원 배열이 실질적으로 컴퓨터 메모리에 어떻게 저장되는지를 확인해보자.

 

예를들어 2차원 배열 int arr[n][m]; 의 경우 n행 m열의 2차원 표의 형태로 저장될 것 같은 기분이 든다. 그러나 실제로는 1차원 배열에서 처럼 연속적인 메모리 공간에 할당되는데, 이때 C는 배열을 행 우선 순서로 저장하게 된다. 아래 교재의 그림을 참고하면 쉽게 이해할 수 있다.

3. 가변크기 배열

C 언어에서는 배열이 고정된 크기를 가지며, 배열의 크기는 상수값이나 상수 표현식으로 지정해야 한다. 그러나 C99에서는 가변 크기 배열(VLA)을 도입하여 배열의 크기를 런타임에 동적으로 결정할 수 있도록 하였다. 이를 통해 사용자 입력이나 계산된 값을 배열의 크기로 사용할 수 있다. VLA는 함수 내에서 선언할 수 있으며, 함수가 호출될 때마다 다른 크기를 가질 수 있는 장점이 있다. 그러나 VLA는 스택에 할당되므로, 큰 배열 크기를 사용할 경우 스택 오버플로우의 위험이 있으며, C89/C90과의 호환성 문제도 고려해야 한다. 

 

VLA 예시코드는 다음과 같다.

#include <stdio.h>

int main() {
    int n;

    // 사용자로부터 배열의 크기를 입력받음
    printf("Enter the size of the array: ");
    scanf("%d", &n);

    // 가변 크기 배열 선언
    int arr[n];  // C99에서 VLA를 사용하여 배열 크기를 n으로 설정

    // 배열에 값 할당
    for (int i = 0; i < n; i++) {
        arr[i] = i * 2;  // 예시로 짝수값 할당
    }

    // 배열 값 출력
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}