본문 바로가기
c언어

c언어 이중 포인터에 대하여 알아보기

by 개발자 L 2023. 2. 4.
반응형

c언어 이중 포인터에 대하여 알아보기

네 안녕하세요, 이번 포스팅에서는 c언어에서 사용하는 포인터 중 하나인 이중 포인터에 대하여 알아보겠습니다.

제가 포스트를 작성하면서 포인터는 활용 분야가 넓다고 한 적이 있습니다.

이중 포인터 역시 이러한 포인터 중 하나입니다.

그리고 정말 많이 쓰는 포인터들 중 하나이기도 합니다.

그래서 정말 중요한 파트이니, 양질의 정보를 얻어가셨으면 하는 바람입니다.

그럼 지금부터 시작하도록 하겠습니다.

 

1. 이중 포인터

이중 포인터란 쉽게 말해서 포인터를 가리키는 포인터입니다.

포인터를 가리키는 포인터.. 들었을 때는 정말 생소하고 이해가 잘 되지 않으실 수 있을 겁니다.

하지만 이게 가능합니다.

그 이유는 포인터는 어떤 변수의 주소값을 가지고 있는 변수입니다.

그리고 우리가 쓰는 포인터 변수 역시 하나의 변수이기 때문에 주소가 존재합니다.

다시 말하면 이 포인터 변수의 주소를 또 다른 포인터에 넣으면 그게 포인터를 가리키는 포인터,

즉, 이중 포인터가 되는 것입니다.

이중 포인터는 이런 식으로 씁니다.

int **q // int형 포인터 변수를 가리키는 포인터(이중 포인터)

이런 식으로 에스터리스크를 두 개 붙여주시면 됩니다.

그러면 우리가 이제 선언하는 방법을 알았습니다.

그럼 이제 이걸 어떻게 쓰는 지를 알아야겠죠?

사용 방법은 이러합니다.

int i = 1000;
int *p = &i; // int형 변수 i를 가리키는 포인터 변수 p
int **q = &p; // int형 변수 i를 가리키는 포인터 변수인 p를 가리키는 이중 포인터 변수 q

사용 방법은 그렇게 어렵지 않습니다.

그냥 포인터를 중첩해서 쌓아 올린다는 느낌으로다가 전에 쓰인 변수의 주소를 가리킨다고 생각하시면 편합니다.

또한, 포인터를 이용하여 원본에 접근해 값을 변경할 수 있듯이, 이중 포인터를 이용해도 값을 변경시킬 수 있습니다.

이렇게 말이죠.

*p = 200; // i의 값을 200으로 변경
**q = 300; // i의 주소를 가리키는 변수인 p에 접근했으므로, i의 값을 300으로 변경

이렇게 되는 겁니다.

그럼 이걸 이용해서 간단한 예제를 한 번 작성을 해보도록 하겠습니다.

#include <stdio.h>

int main()
{
    int i = 100;
    int *p = &i;
    int **q = &p;

    *p = 200;

    printf("i = %d\n", i);

    **q = 300;

    printf("i = %d\n", i);

    return 0;
}

이렇게 기본 포인터와 이중 포인터의 기능을 보여주기 위해 간단하게 코드를 작성했습니다.

그럼 결과가 어떻게 나오며, i의 값이 어떤 식으로 변하는지 보도록 하겠습니다.

i = 200
i = 300

이렇게 기본 포인터가 가리켜도 값이 변하고, 이중 포인터가 가리켜도 값이 변하는 것을 확인할 수 있습니다.

반응형

 

2. 이중 포인터가 가장 많이 사용되는 경우

이중 포인터가 가장 많이 사용되는 경우는 외부에서 정의된 포인터의 값을 함수의 인수로 받아서 변경할 때가 가장 많습니다.

보통 기본 소스는 기본 포인터만 쓰는 경우가 많은데,

실제로 프로그래밍을 하다 보면 외부에 있는 값을 참조해야 하는 경우가 생기는데,

그때 포인터를 참조해야 하는 경우가 생깁니다.

그래서 그럴 경우에 정말 많이 씁니다.

이중 포인터를 통해서 기본 포인터가 가진 주소에 들어가 원본을 참조하는 것이죠.

그럼 이러한 경우를 보여주는 소스 코드를 한 번 작성을 해보도록 하겠습니다.

#include <stdio.h>

void set_pointer(char **q);

int main()
{
    char *p;

    set_pointer(&p);

    printf("오늘의 격언 : %s\n", p);

    return 0;
}

void set_pointer(char **q)
{
    *q = "All that glisters is not gold.";
}

이렇게 작성을 해봤습니다.

함수 외부에 선언이 되어있는 걸 끌어와서 변경을 하는 코드입니다.

그리고 여기서 보면 알 수 있듯이, **q는 *(q)로 볼 수도 있는데,

q가 가리키는 값인 *q가 포인터가 되고,

이 포인터 *q가 가리키는 값이 *(*q)가 됨을 볼 수 있습니다.

그러면 결과를 보도록 하겠습니다.

오늘의 격언 : All that glisters is not gold.

제대로 참조가 되어 출력이 된 것을 확인할 수가 있습니다.

그리고 여기서 주의를 해야 할 점이 있는데,

대다수의 사람들이 이런 실수를 해서 에러를 냅니다.

int main()
{
    ...
    set_pointer(p);
    ...
}

void set_pointer(char *q)
{
    q = "All glisters is not gold.";
}

이럴 경우에는 어떤 일이 벌어지느냐,

포인터의 값만 복사가 됩니다.

다시 말하면 q를 아무리 변경을 한들, p는 전혀 변경이 안 되는 것입니다.

그 이유는 포인터는 주소를 받아 접근하는 원리인데, main 함수를 보면 p 앞에 엠퍼센드가 빠진 것을 볼 수가 있을 겁니다.

이럴 경우에는 p의 주소에 접근을 할 수 없기 때문에 아무리 값을 변경하려 해도 변경이 되지 않습니다.

이 점을 주의하여 작성하셔야 합니다.

 

여기까지 이중 포인터에 대하여 알아보았는데요,

다음 포스팅에서는 포인터 배열에 대하여 알아보도록 하겠습니다.

긴 글 읽어주신 독자분들께 진심으로 감사드립니다~

반응형

댓글