ABOUT ME

꾸준히 성장하는 토리 기록

  • 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차원적으로 저장된다는 점을 이해하면 좀 더 쉽게 받아들일 수 있습니다.

     

    다들 정처기 공부 화이팅입니다~~~

    댓글

SSOONTORY Blog.