정적 배열과 동적 배열에 대해 정리한 글입니다. 기본 개념과 특징을 중점으로 정리하였습니다.
정적 배열 (Static Array)
정적 배열의 정의
- 정적 배열은 배열의 크기가 컴파일 시 결정되는 배열의 의미
- 일반적으로 스택 영역(stack section)에 할당되며, 프로그램이 시작될 때 필요한 메모리 공간을 이미 확보한 상태로 실행
메모리 구조
스택 영역 할당
- 일반적으로 함수 내부에 정적 배열을 선언하면, 해당 함수가 호출될 때 스택에 고정된 크기의 메모리가 할당됨
- 함수가 종료되면 스택이 정리되면서 배열도 소멸함
고정 크기
- 배열의 크기를 변경할 수 없음
- ex.
int arr[10];으로 선언한 배열은 10개의int공간을 항상 차지함 (변경 불가)
- ex.
정적 배열의 장단점
장점
- 접근 속도가 빠름
- 모든 요소가 연속적인 메모리에 저장되기 때문에 인덱스를 이용한 랜덤 액세스가 $ O(1) $ 시간에 가능
- 단순한 선언과 해제
- 별도의 동적 메모리 관리 함수(
malloc,free등)를 호출하지 않아도 됨 - 선언과 동시에 메모리가 할당되고, 스코프가 끝날 때 자동으로 해제됨
- 별도의 동적 메모리 관리 함수(
- 메모리 접근의 예측 가능성
- 소멸 시점이 명확힉 때문에 메모리 누수(memory leak)에 대한 위험이 없음
단점
- 크기 변경 불가
- 배열 크기를 확장하거나 축소할 수 없으므로, 프로그램 실행 중에 필요한 크기가 달라지면 재설계가 필요
- 스택 메모리 제한
- 대규모 배열을 선언할 경우, 스택 오버플로우(stack overflow)가 발생할 수 있음
- 재사용 유연성 낮음
- 다른 함수에서 이 배열을 공용으로 사용하기 어렵거나, 사용할 경우 전역 변수로 두어야 해 결합도(coupling)가 높아질 수 있음
주의 사항
- 함수 안에서 큰 크기의 배열을 선언할 때에는 스택 사용량 고려가 필요 (스택 오버플로우를 일이킬 수 있는지 확인)
- 전역(파일 범위) 변수를 사용할 때 메모리 사용량을 면밀히 파악하고, 다른 모듈 및 함수와 결합도를 낮추도록 설계 필요
사용 예시
- 크기가 확실하게 정해져 있는 경우
- ex. 고정된 크기의 테이블을 생성하여 간단한 조회 용도로 사용하는 경우
- 임베디드 시스템
- 메모리 용량이 제한된 환경에서, 정적 할당으로 안전하게 메모리를 관리해야 할 때 활용
동적 배열 (Dynamic Array)
동적 배열의 정의
- 동적 배열은 프로그램 실행 중에 메모리를 할당받아 크기를 자유롭게 결정하는 배열을 의미
- C 혹은 C++에서는 주로
malloc,calloc,realloc,free(C 언어)나new,delete(C++) 등을 통해 힙 영역(heat section)에 메모리를 할당하고 관리함
메모리 구조
힙 영역 할당
- 동적 배열은 스택이 아닌 힙(heap)에서 메모리를 할당받음
- 프로세스의 런타임 상황에 따라 필요한 크기만큼 메모리를 요구하고, 사용이 끝나면 반드시 직접 해제해줘야 함
크기 변경(재할당) 가능
realloc(C 언어 함수)을 사용하거나,, C++ STL의std::vector같은 자료구조를 사용하면 필요 시 배열 크기를 조절할 수 있음
동적 배열의 장단점
장점
- 유연성
- 실행 중에 사용자가 원하는 크기만큼 배열 공간을 할당할 수 있으므로, 상황에 따라 메모리를 효율적으로 사용할 수 있음
- 재할당을 통한 확장
realloc등을 사용해 배열 크기를 확장 가능- 단, 내부 구현상 새로운 메모리 공간을 할당하고 기존 데이터를 복사할 수도 있음
- 스택 오버플로우 방지
- 힙 영역을 사용하는 덕분에, 큰 용량의 배열이 필요한 경우에도 스택 영역에 부담을 주지 않음
단점
- 메모리 관리의 복잡성
- 사용 후에 반드시 해제(
free/delete)해야 하며, 해제하지 않으면 메모리 누수가 발생
- 사용 후에 반드시 해제(
- 할당 실패 가능성
- 힙 공간이 부족하면 동적 메모리 할당이 실패할 수 있으며, 할당 실패에 대한 예외 처리가 필요
- 재할당 시 비용 발생
- 배열 크기를 변경하기 위해 재할당(
realloc)이 발생하면, 새로 할당받은 메모리로 데이터를 복사하는데 $ O(n) $ 시간이 소요될 수 있음
- 배열 크기를 변경하기 위해 재할당(
- 추가 오버헤드
- 힙 메모리는 스택에 비해 할당 및 해제 자체가 무거운 연산이며, 메모리 단편화(fragmentation)가 발생할 수 있음
주의 사항
- 할당받은 메모리를 사용한 뒤에는 반드시 해제해야 하며, 중복 해제(double free)나 잘못된 포인터(invalid pointer) 참조에 주의가 필요
- 예외(Exception)나 에러 발생 시에도 제대로 해제할 수 있도록 RAII(Resource Acquisition Is Initialization) 패턴이나
smart pointer(C++에서unique_ptr,shared_ptr))등을 활용하는 것이 좋음 realloc혹은 내부 구현상 배열이 재할당될 경우 (ex. C++에서std::vector가 용량을 확장하는 경우) 이전 포인터가 무효화될 수 있어 포인터 사용 시 주의가 필요
사용 예시
- 크기를 알 수 없거나 변동이 많은 경우
- ex. 사용자 입력에 따라 데이터 개수가 달라질 수 있는 프로그램
- C++ STL의
std::vector- 내부적으로 동적 배열을 이용하며, 필요 시 자동으로 학장
- 사용자느 ㄴ인덱스를 이용해 접근하거나, 동적 크기를 다룰 수 있어 편리함
- 임시 버퍼 및 대규모 데이터 처리
- 파일 입출력, 네트워크 패킷 처리 등에서 런타임에 필요한 크기만큼 배열을 할당하고 작업이 끝나면 해제함
정적 배열과 동적 배열 비교
| 항목 | 정적 배열 (Static Array) | 동적 배열 (Dynamic Array) |
| 메모리 할당 시점 | 컴파일 시 (또는 함수 호출 시 스택에 할당) |
런타임 시 (힙 영역에 할당) |
| 크기 변경 가능 여부 | 불가능 | 가능 (재할당을 통한 확장 / 축소) |
| 할당 / 해제 관리 | 자동 (스코프 종료 시 해제) |
수동 ( free, delete 등 사용) |
| 장점 | 간단한 선언 및 접근 빠른 접근 속도 예측 가능한 메모리 사용 |
런타임에 유연한 크기 결정 확장 / 축소 가능 대규모 데이터 처리 용이 |
| 단점 | 크기 변경 불가 스택 메모리 제한 재사용 어려움 |
메모리 누수 위험 재할당 시 복사 비용 힙 단편화 가능성 |
| 대표적 사용 예시 | 컴파일 시 크기가 고정된 데이터 임베디드 환경 |
사용자 입력, 파일, 네트워크처럼 크기 변화가 많은 데이터 std::vector, 동적 버퍼 |
핵심 요약
- 정적 배열
- 크기가 고정적이고, 컴파일 시점에 확정되는 경우 유리함
- 선언과 해제 과정이 간단하며, 스코프가 명확함
- 동적 배열
- 크기가 유동적이고 변동 사항이 많을 때 유용함
- 메모리 관리를 직접 해야 하므로, 메모리 누수와 같은 오류에 주의가 필요
'🧠 CS > 자료구조' 카테고리의 다른 글
| [자료구조] C++ Container Library : Sequential Containers - vector (0) | 2025.04.26 |
|---|---|
| [자료구조] 우선순위 큐(priority queue)의 정렬 안정성 (0) | 2025.04.06 |
| [자료구조] 서로소 집합 자료구조 (Disjoint Set Union, DSU) - Union Find (0) | 2025.03.03 |
| [자료구조] 스택(Stack)과 큐(Queue) (0) | 2025.02.27 |
| [자료구조] 배열(Array)과 DAT(Direct Access Table) (0) | 2025.01.27 |