-
C언어 개념 정리 (포인터 배열)카테고리 없음 2025. 3. 30. 20:05
포인터 배열은 각 요소가 포인터인 배열입니다.
해당 개념이 이해가 잘 가지 않아서 고생을 한 1인으로서... 제가 이해를 위해 공부했던 내용들을 공유드립니다.
해당 개념 이해를 좀 더 잘 하기 위해 메모리 구조와 함께 해당 개념을 이해해보고자 합니다.
1. 2차원 배열의 메모리 구조
2차원 배열은 메모리에서 행(row)마다 연속된 블록으로 저장됩니다.
아래는 2차원 배열의 구조입니다.
int matrix[3][4] = { {1, 2, 3, 4}, // 첫 번째 행 {5, 6, 7, 8}, // 두 번째 행 {9, 10, 11, 12} // 세 번째 행 };
2차원 배열은 메모리 상에서 다음과 같이 연속적으로 배치됩니다:
낮은 주소 ──────────────────────────────────────────> 높은 주소 +----+----+----+----+----+----+----+----+----+----+----+----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | +----+----+----+----+----+----+----+----+----+----+----+----+ ↑ 행 0 ↑ 행 1 ↑ 행 2 matrix[0][0] matrix[1][0] matrix[2][0]
위에서도 볼 수 있듯, 2차원 배열은 모든 요소가 연속적인 메모리 공간에 저장됩니다.
2. 포인터 배열의 메모리 구조
포인터 배열은 뭘까요? 말 그대로 각각의 요소가 포인터인 배열입니다.
int *ptr_array[3]; // 3개의 int 포인터를 담는 배열 int a = 1, b = 2, c = 3; ptr_array[0] = &a; //ptr_array[0]는 a의 주소를 가르킨다. ptr_array[1] = &b; //ptr_array[1]는 b의 주소를 가르킨다. ptr_array[2] = &c; //ptr_array[2]는 c의 주소를 가르킨다.
메모리 구조
포인터 배열 자체: +-------------+-------------+-------------+ | ptr_array[0]| ptr_array[1]| ptr_array[2]| | (주소 &a) | (주소 &b) | (주소 &c) | +-------------+-------------+-------------+ 가리키는 변수들 (메모리의 다른 위치에 있을 수 있음): +---+ +---+ +---+ | 1 | | 2 | | 3 | +---+ +---+ +---+ ↑ ↑ ↑ a b c
포인터 배열의 메모리 구조를 보면, 배열 자체는 연속된 메모리에 저장되지만, 가리키는 데이터는 메모리 어디에나 있을 수 있습니다.
각 요소는 주소(포인터)를 저장하고 있습니다.
3. 포인터 배열을 2차원 배열처럼 사용
포인터 배열을 사용하여 2차원 배열과 유사한 구조를 만들 수 있습니다.
(수제비 교제에서 이 부분이 너무 어려워 해당 개념을 정리하기로 마음 먹었습니다.... . ㅠㅠㅠㅠ)
배열의 메모리 구조
2차원 배열은 실제로 메모리에서 1차원적으로 연속 배치됩니다. 예를 들어, 다음과 같은 2차원 배열이 있다면
int a[3][2] = { {1, 2}, // 첫 번째 행 {3, 4}, // 두 번째 행 {5, 6} // 세 번째 행 };
메모리에서는 다음과 같이 연속적으로 저장됩니다:
1, 2, 3, 4, 5, 6
이 점을 이해하지 못하면 포인터로 배열에 접근할 때 혼란스러울 수 있습니다.
배열 이름과 포인터
배열 이름은 배열의 첫 번째 요소의 주소를 나타냅니다. 이 개념을 잘 이해해야 포인터 개념을 이해할 수 있답니다..
- a는 전체 배열의 시작 주소
- a[0]은 첫 번째 행의 시작 주소
- a[1]은 두 번째 행의 시작 주소
포인터를 통한 배열 접근
포인터 변수가 배열의 특정 위치를 가리킬 때, 인덱싱을 통해 접근하는 방법을 이해하기 어려웠습니다:
int *p = a[1]; // p는 a[1][0]의 주소를 가리킴
- p[0]은 p가 가리키는 위치의 값 = a[1][0] = 3 (이 개념부터 이해하기~~~!!!!)
- p[1]은 p가 가리키는 위치에서 한 칸 뒤의 값 = a[1][1] = 4
- 베열은 메모리에 저장될때 연속적으로 저장된다는 것을 반드시 숙지해야 위 말이 이해가 될 것입니다!
- p[-1]은 p가 가리키는 위치에서 한 칸 앞의 값 = a[0][1] = 2
즉, p[i]는 "p가 가리키는 주소에서 i만큼 떨어진 위치의 값"을 의미합니다.
배열을 연속된 메모리 저장소로 생각하면 포인터를 통한 접근을 이해하기 쉬워집니다.
포인터는 단순히 메모리의 특정 위치를 가리키고, 그 위치를 기준으로 상대적인 접근이 가능합니다.
메모리 구조를 다음과 같이 시각화하면 이해하기 쉽습니다:
메모리 주소: 1000 1004 1008 1012 1016 1020 배열 요소: a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] 값: 1 2 3 4 5 6 ↑ p (p = a[1], 주소 1008)
p가 a[1][0]을 가리키면, p[0]은 주소 1008의 값(3), p[1]은 주소 1012의 값(4), p[-1]은 주소 1004의 값(2)가 됩니다.
C 언어의 배열과 포인터는 메모리의 구조와 직접적으로 연결되어 있기 때문에 해당 개념을 반드시 숙제해야 문풀에 도움이 됩니다.
2차원 배열이 실제로는 메모리에 1차원적으로 저장된다는 점을 이해하면 좀 더 쉽게 받아들일 수 있습니다.
다들 정처기 공부 화이팅입니다~~~