C 배열 포인터 - sonkoni/Koni-Wiki GitHub Wiki

포인터배열 vs 배열포인터

괄호의 유무에 따라 의미가 달라진다.

== 포인터배열: 배열이다. ==
자료형 *배열이름[카운트];       // `자료형으로 된 포인터`를 카운트만큼 담을 수 있는 배열
int *numPtrArr[4];        // `int 형 포인터`를 4개 담을 수 있는 배열

== 배열포인터: 포인터이다. ==
자료형 (*포인터이름)[카운트];   // `자료형 요소를 카운트만큼 가지고 있는 배열`을 가리키는 포인터
int (*numArrPtr)[4];      // `int 요소 4개를 가지고 있는 배열`을 가리키는 포인터

배열과 포인터

#include <stdio.h>
int main(int argc, char *argv[]) {
    int nArr[4] = {11, 12, 13, 14};
    printf("nArr: %p, %p\n", &nArr, nArr);
    printf("nArr: %p, %d\n", &nArr[0], nArr[0]);
    return 0;
}
// nArr: 0x7ff7bbb525b0, 0x7ff7bbb525b0
// nArr: 0x7ff7bbb525b0, 11

배열은 특이하다. 배열은 0번인덱스의 포인터주소이다. 따라서 &nArrnArr&nArr[0]은 같다.

포인터배열

#include <stdio.h>
int main(int argc, char *argv[]) {
    int a, b, c;
    a = 1, b = 2, c = 3;

    int *aPtr = &a;
    int *bPtr = &b;
    int *cPtr = &c;

    int *numPtrArr[3] = {aPtr, bPtr, cPtr};

    printf("%p, %p\n", numPtrArr[0], aPtr);
    printf("%p, %p\n", numPtrArr[1], bPtr);
    printf("%p, %p\n", numPtrArr[2], cPtr);

    printf("%d, %d\n", *numPtrArr[0], *aPtr);
    printf("%d, %d\n", *numPtrArr[1], *bPtr);
    printf("%d, %d\n", *numPtrArr[2], *cPtr);

    return 0;
}
// 0x7ff7beb6d59c, 0x7ff7beb6d59c
// 0x7ff7beb6d598, 0x7ff7beb6d598
// 0x7ff7beb6d594, 0x7ff7beb6d594
// 1, 1
// 2, 2
// 3, 3

포인터배열은 포인터를 담고 있는 배열이다. numPtrArr[0]aPtr과 같다.

포인터배열과 2차원배열

#include <stdio.h>
int main(int argc, char *argv[]) {
//    int numArr[3][4] = {
//        {11, 12, 13, 14},
//        {21, 22, 23, 24},
//        {31, 31, 33, 34}
//    };

    int n0Arr[4] = {11, 12, 13, 14};
    int n1Arr[4] = {21, 22, 23, 24};
    int n2Arr[4] = {31, 31, 33, 34};

    int *nPtrArr[3] = {n0Arr, n1Arr, n2Arr};

    printf("%p, %p\n", nPtrArr[0], n0Arr);
    printf("%zu, %zu\n", sizeof(nPtrArr[0]), sizeof(n0Arr));
    printf("%d, %d\n", nPtrArr[0][1], n0Arr[1]);

    return 0;
}
// 0x7ff7b243d5b0, 0x7ff7b243d5b0
// 8, 16
// 12, 12

포인터를 담을 수 있는 배열이 포인터배열이다. 이 배열 요소에 또 배열을 꽂으면 2차원 배열이 된다. 위의 numPtrArr 은 2차원 배열인 numArr과 같다. 다만 포인터는 포인터 주소의 크기로 계산되는 반면, 배열은 배열 크기로 계산된다.

배열포인터

#include <stdio.h>
int main(int argc, char *argv[]) {
    int nArr[4] = {11, 12, 13, 14};
    int (*nArrPtr)[4] = &nArr;
    printf("%p: %p, %p\n", nArrPtr, *nArrPtr, nArr);
    printf("%zu: %zu, %zu\n", sizeof(nArrPtr), sizeof(*nArrPtr), sizeof(nArr));
    printf("%d, %d\n", (*nArrPtr)[1], nArr[1]);
    return 0;
}
// 0x7ff7bd7775b0: 0x7ff7bd7775b0, 0x7ff7bd7775b0
// 8: 16, 16
// 12, 12

배열포인터는 배열을 포인터로 한 번 더 뺀 것이다. 사실상 *nArrPtrnArr과 같다. 다만 포인터의 사이즈는 포인터 주소의 사이즈로 계산되는 반면 배열은 전체 크기로 계산된다.

배열포인터와 2차원배열

== 2차원 배열을 배열포인터 할당 ==
자료형 (*포인터이름)[가로갯수];

```c
#include <stdio.h>
int main(int argc, char *argv[]) {
    int numArr[3][4] = {
        {11, 12, 13, 14},
        {21, 22, 23, 24},
        {31, 31, 33, 34}
    };
    // 2차원배열 numArr 은 사실 {요소가4인배열, 요소가4인배열, 요소가4인배열} 이다.
    // 2차원배열 numArr 의 주소는 numArr의 0번인덱스의 주소(`요소가4인배열`의 주소)이다.
    
    // int **numPtr = numArr; /*** WRONG 자료형이 다르므로 2차원 배열은 이중포인터에 넣을 수 없다. ***/
        
    // 배열포인터
    int (*numPtr)[4]; // `요소가4인배열`을 가리키는 포인터
    numPtr = numArr;
    
    printf("%p, %p\n", *numPtr, *numArr);
    printf("%d, %d\n", numPtr[2][1], numArr[2][1]);
    printf("%zu, %zu", sizeof(numPtr), sizeof(numArr));
    
    return 0;
}
// 0x7ff7bf147590, 0x7ff7bf147590
// 31, 31
// 8, 48

2차원 배열은 사실 배열 포인터를 담고 있는 1차원 배열이다. 따라서 배열포인터로 받을 수 있다.

    {11, 12, 13, 14}
            ▲
            │
numArr = {{r0}, {r1}, {r2}}
            ▲
            │
     int (*numPtr)[4]

여기서 numPtrnumArrnumArr[0]은 같다. 다만 포인터의 사이즈는 포인터 주소의 사이즈로 계산되는 반면 배열은 전체 크기로 계산된다.

⚠️ **GitHub.com Fallback** ⚠️