배열의 메모리 구조
연속된 메모리 공간에 동일한 타입의 데이터를 저장하는 자료구조
핵심 개념
연속된 메모리 할당
메모리 주소: 1000 1004 1008 1012 1016
+------+------+------+------+------+
배열 arr: | 10 | 20 | 30 | 40 | 50 |
+------+------+------+------+------+
인덱스: [0] [1] [2] [3] [4]
- 배열의 모든 요소는 연속된 메모리 공간에 저장된다
- 각 요소는 동일한 크기의 메모리를 차지한다
인덱스를 통한 O(1) 접근
요소의 주소 = 시작 주소 + (인덱스 × 요소 크기)
arr[3]의 주소 = 1000 + (3 × 4) = 1012
- 인덱스만 알면 단 한 번의 계산으로 해당 요소에 접근 가능
- 이것이 배열의 가장 큰 장점: Random Access O(1)
코드 예시
Java
int[] arr = new int[5]; // 연속된 20바이트 할당 (4바이트 × 5)
arr[0] = 10;
arr[3] = 40; // O(1) - 바로 접근C
int arr[5];
int* ptr = arr; // 배열의 시작 주소
int third = *(ptr + 2); // arr[2]와 동일, 포인터 연산메모리 레이아웃 상세
1차원 배열
int arr[4] = {1, 2, 3, 4};
Stack Memory:
+------+------+------+------+
| 1 | 2 | 3 | 4 |
+------+------+------+------+
arr arr+1 arr+2 arr+3
2차원 배열 (Row-Major Order)
int matrix[2][3] = {{1,2,3}, {4,5,6}};
메모리 배치 (행 우선):
+---+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 | 6 |
+---+---+---+---+---+---+
[0,0][0,1][0,2][1,0][1,1][1,2]
matrix[i][j]의 주소 = base + (i × 열개수 + j) × 요소크기
캐시 친화성 (Cache Locality)
배열은 캐시 히트율이 높다:
CPU가 arr[0]을 읽을 때:
1. arr[0]~arr[N]이 캐시 라인에 함께 로드됨
2. 이후 arr[1], arr[2]... 접근 시 캐시에서 바로 읽음
3. 연결리스트 대비 실제 성능이 훨씬 좋음
면접 포인트
-
왜 O(1) 접근이 가능한가?
- 연속된 메모리 + 동일한 요소 크기 → 주소 계산 공식
-
배열의 메모리 할당 위치는?
- 지역 변수 배열: 스택
- 동적 할당 (new, malloc): 힙
-
2차원 배열 순회 시 왜 행 우선이 빠른가?
- 메모리가 행 우선으로 저장되므로 캐시 히트율이 높음
-
배열의 단점은?
- 크기 고정 (정적 배열)
- 삽입/삭제 시 요소 이동 필요 O(n)