배열(Array)은 동일한 데이터 타입의 요소들을 고정된 크기만큼 순차적으로 저장하는 자료구조입니다. 배열은 여러 개의 데이터를 하나의 이름으로 묶어 관리할 수 있게 해주며, 같은 타입의 변수들이 모여 있다고 생각하면 이해하기 쉽습니다.
배열은 매우 유용한 자료구조지만, C 언어에서 배열을 사용할 때는 몇 가지 중요한 한계점을 반드시 알고 있어야 합니다. 이러한 한계를 모른 채 사용하면 예측하기 어려운 버그나 프로그램 비정상 종료로 이어질 수 있습니다.
C 언어 배열의 주요 한계점
1. 동질성(Homogeneous) 제약
배열은 선언된 순간 하나의 데이터 타입만 저장할 수 있습니다. 즉, 정수형(int) 배열에는 정숫값만, 실수형(float) 배열에는 실숫값만, 문자형(char) 배열에는 문자만 저장할 수 있습니다. 따라서 하나의 배열에 서로 다른 두 가지 이상의 데이터 타입을 함께 담는 것은 불가능합니다.
2. 크기 선언 필수 및 고정 크기 문제
배열을 선언할 때는 반드시 배열의 크기를 지정해야 하며, 그 크기는 상수(constant)여야 합니다. 실행 중에 필요한 만큼 유연하게 크기를 조절할 수 없기 때문에, 실제 필요한 데이터보다 크기를 작게 잡으면 메모리가 부족하고, 너무 크게 잡으면 메모리가 낭비되는 문제가 발생합니다.
3. 삽입·삭제 시 요소 이동(Shifting) 필요
배열의 중간에 새로운 요소를 삽입하거나 기존 요소를 삭제하려면, 뒤따르는 모든 요소를 한 칸씩 이동시켜야 합니다. 이 과정은 추가적인 연산 비용을 발생시키며, 데이터가 많을 경우 성능 저하의 원인이 됩니다.
4. 경계(Boundary) 검사 미제공
C 언어는 배열에 입력되는 값이 배열의 크기를 초과하는지 자동으로 검사하지 않습니다. 즉, 프로그래머가 직접 인덱스 범위를 관리해야 하며, 컴파일러나 런타임이 이를 대신 잡아주지 않습니다.
5. 범위 초과 데이터의 외부 저장 문제
첨자(subscript)를 사용해 입력한 데이터가 배열의 크기를 초과하면, 해당 값은 배열 바깥의 메모리 영역에 저장됩니다. 일반적으로 그 위치는 다른 데이터 위쪽이거나 프로그램 자체의 메모리 영역입니다.
6. 예측 불가능한 결과와 오류 메시지 부재
배열 범위를 벗어난 접근은 최악의 경우 예측할 수 없는 결과를 낳습니다. 게다가 배열 크기를 초과했다는 경고나 오류 메시지가 전혀 표시되지 않으므로, 프로그래머가 실수를 인지하기 어렵습니다. 심한 경우 프로그램이 멈추거나(hang) 비정상 종료될 수 있습니다.
범위 초과 접근의 위험성을 보여주는 코드
다음 프로그램처럼 배열 크기를 초과하는 반복문을 작성하면 의도하지 않은 결과가 발생할 수 있습니다.
int a[10], i;
for(i = 0; i <= 20; i++) // 배열 크기(10)를 초과하는 접근!
a[i] = i;위 코드에서 배열 a는 10개의 요소만 가질 수 있지만, 반복문은 인덱스 20까지 접근합니다. 이렇게 되면 배열 밖의 메모리를 덮어쓰게 되어 프로그램 전체에 심각한 문제를 일으킬 수 있습니다.
예제: 두 배열의 합 구하기
다음은 올바른 방식으로 배열을 활용하는 C 프로그램 예제입니다. 두 개의 배열을 입력받아 각 요소의 합을 새로운 배열에 저장하고 출력합니다.
#include<stdio.h>
void main(){
// 컴파일 타임에 배열 선언 //
int array1[5], array2[5], sum[5];
// 변수 선언 //
int i;
// for 반복문으로 입력 받기 //
printf("Enter the values of array1 :\n");
for(i = 0; i < 5; i++){
printf("array1[%d] : \n", i);
scanf("%d", &array1[i]);
}
printf("Enter the values of array2 :\n");
for(i = 0; i < 5; i++){
printf("array2[%d] :\n", i);
scanf("%d", &array2[i]);
}
printf("Elements in the sum of array1 and array2 are:\n ");
for(i = 0; i < 5; i++){
sum[i] = array1[i] + array2[i];
printf("%d ", sum[i]);
}
}실행 결과
위 프로그램을 실행하면 다음과 같은 결과가 출력됩니다.
Enter the values of array1 : array1[0] : 2 array1[1] : 3 array1[2] : 1 array1[3] : 2 array1[4] : 3 Enter the values of array2 : array2[0] : 4 array2[1] : 5 array2[2] : 3 array2[3] : 2 array2[4] : 1 Elements in the sum of array1 and array2 are: 6 8 4 4 4
마치며
C 언어의 배열은 단순하고 빠른 자료구조이지만, 고정 크기, 단일 타입 제약, 경계 검사 부재라는 명확한 한계를 가지고 있습니다. 특히 배열 범위를 벗어나는 접근은 별도의 오류 메시지 없이 조용히 프로그램을 망가뜨릴 수 있으므로, 반복문의 인덱스 범위(i < 배열크기)를 항상 꼼꼼히 확인하는 습관이 중요합니다. 더 유연한 크기 조절이 필요하다면 동적 메모리 할당(malloc, realloc)이나 연결 리스트(linked list) 같은 대안을 고려해 보는 것도 좋은 방법입니다.