본문 바로가기

C++/C++ 지식

포인터(Pointer)? - C++

SMALL

포스팅 계기

 현업을 진행하다 보면 개발자에 막 입문한 초보 개발자들에게 질문을 많이 받는다. 그중 최근에 같이 일을 하게 된 새로운 개발자가 포인터에 관해 이해가 부족하여 코드적으로 실수를 하는 것을 보았다. 그 이후 포인터에 관해 대화를 하였는데, 아직까지도 잘 모르겠다고 나에게 이야기했다. 최근 티스토리에 포스팅을 안 한지도 오래되었고, 그분에게 도움이 되었으면 하는 바람에 "포인터(Pointer)"를 주제로 포스팅하게 되었다. 최대한 처음 보는 사람 입장에서도 이해가 될 수 있게 글을 작성할 수 있도록 노력하였으며, 혹여나 글을 보고 이해가 어려운 부분이 있다면 댓글로 문의 남겨주면 친절하게 답변할 수 있도록 하겠다.


포인터(Pointer)란?

 포인터란 무엇일까? Pointer를 번역하면 바늘, 가리키는 사람, 가리키는 것으로 해석이 된다. 개발에서 포인터란 가리키는 것으로 이해하는 것이 편하다. 그래서 나만의 포인터 정의를 해보았다.

더보기

 포인터(Pointer) : 메모리의 주소를 가리키는 변수

 이해를 돕기 위해 메모리를 우리가 살고 있는 세상에 비유해보려고 한다. 우리가 살고 있는 나라는 대한민국이다. 대한민국에서도 우리가 살고 있는 공간은 고유한 주소를 가진다. 

포인터 설명 예제 1

 

 위의 자료를 가지고 내가 X라는 주소에 어떤 구성원이 살고 있는지 알고 싶을 때 우리가 주소를 알고 있으면 바로 사는 사람이 누구인지 알 수 있을 것이다. 그때 그 주소 정보를 가지고 있는 변수를 포인터(Pointer)라고 한다. 이것을 코드를 통해 한 번 예시를 들어보겠다.

 

 우리가 코딩을 할 때 본인이 원하는 Type의 변수를 만들어서 보통 값을 할당한다. 우리는 지금 가족 구성원을 저장해야 하기 때문에 하기처럼 string Type의 변수를 하나 선언하여 사는 사람 정보를 할당하였다. 이때 sFamily는 사는 사람에 대한 정보가 들어있는 것이다. 그러면 sFamily가 어디에 위치하는지 알고 싶을 때 포인터(Pointer)를 사용할 수 있다. 우리가 개발을 할 때 포인터는 *라는 기호로 사용을 하게 된다.

string sFamily = "XXX, YYY 등";
string *pAdress = &sFamily;

 

 그래서 string *pAdress = &sFamily는 sFamily가 위치한 주소를 가리키는 변수가 되는 것이다. 근데 여기서 갑자기 해당 포스팅을 보는 사람들은 &는 또 머야라고 할 수 있다. &는 포인터와는 각별한 사이인데, 아마 눈치가 빠르거나 이해가 빠른 독자는 구현을 보고 어느 정도 감은 잡았을 것이라 생각이 든다.

 

 우리가 sFamily라는 변수를 선언할 때 해당 변수도 결국 메모리에 저장되게 된다. 하지만 우리가 주소는 모르고 값만 알고 있는 변수다. 하지만 이때 &라는 키워드는 해당 변수가 저장되어 있는 주소를 알려주는 문법이다. & 키워드에 관해서는 많은 포스팅을 할 이야기는 없고, 변수가 저장되어 있는 메모리의 주소를 알고 싶을 때 사용하는 문법이라고 생각하면 편다. 


간단 코드 예제

 아래의 코드가 간단하다고 표현은 하였지만, 포인터의 포인터가 들어가서 이해가 어려울 수는 있다. 하지만 하나하나 넘어가면서 이해를 한다면 큰 문제는 없을 것으로 예상된다.

 

 일단 GetAddress라는 함수를 보면 return 값은 int*이고, 파라미터는 int & rValue다. 여기서 파라미터를 &rValue로 받은 이유는 만약 &를 쓰지 않고 인자로 받게 되면, 해당 함수를 호출할 때 복사 연산이 이루어지면서 int *pTemp = GetAddress(iTemp)를 호출할 때 iTemp와 다른 주소값을 가지게 된다. 스택에서 복사를 하여 사용되기 때문이다. 이와 같은 문제를 방지하기 위해 int &를 사용하여 인자를 받는 것이다. ※해당 내용은 처음 보는 개발자 입장에서는 무슨 소리지? 와 같은? 가 생길 수 있는데, 해당 부분은 나중에 따로 한 번 포스팅을 하도록 하겠다.

그다음 코드는 int* pTemp = &rValue다. 우리가 위에서 배운 것과 같이 &는 변수의 주소 공간을 가리키는 문법이라고 했다. 그렇기 때문에 주소공간을 알기 위해서 &를 사용하는 것이고, 그것을 pTemp라는 포인터 변수에 할당 후 반환하는 것이다.

 

 int main에서는 iTemp라는 변수에 4라는 값을 할당하고, pTemp에 GetAddress함수를 호출 후 iTemp의 주소값을 반환받았다. 그리고 cTemp라는 변수에 *pTemp로 대입을 하였는데, 포인터의 포인터는 다시 해당 주소값에 있는 값을 의미하게 된다. 위의 그림을 주소로 갔다가 다시 값으로 간다고 이해하면 편할 것 같다. 그리고 실행을 하게 되면 4라는 값이 출력되게 된다.

int* GetAddress(int& rValue)
{
    int* pTemp = &rValue;
    return pTemp;
}

int main()
{
    int iTemp = 4;
    int *pTemp = GetAddress(iTemp);

    int cTemp = *pTemp;
    std::cout << cTemp;
}

 코드를 직접 구현해보는 것을 추천하며, 구현 후 이해가 가지 않는 부분은 디버깅을 통해 조사식 및 주소값을 확인하면서 이해하는 것을 추천한다.

 


포스팅을 끝마치면서...

 한 번에 이해하면 좋겠지만, 한 번에 이해가 되지 않을 수 있다. 그럴 때는 연필을 들고 하나하나 적어가면서 주수공간이 가리키는 곳의 가리키는 값은?이라고 생각하면서 그리면 이해할 때 도움이 될 것이라 생각이 든다. 물론 나의 입장에서는 최대한 상대방이 이해할 수 있게 설명을 하였다고 포스팅을 했지만, 상대방 입장에서는 어려울 수 있을 것 같다는 생각도 든다. 포스팅 계기에서 언급한 것과 같이 모르는 내용이 있다면 편하게 댓글 작성을 부탁한다. ※추가로 포인터를 활용하여 linked list(링크드리스트)에서도 단방향, 양방향 자료구조를 직접 구현해보면 포인트롤 이해하는데 큰 도움이 될 것으로 예상이 된다. 이에 따라 다음 포스팅은 linked list를 간단하게 직접 구현해 보는 시간을 가지고자 한다. 많은 관심부탁한다.

'C++ 개발이야기 > C++ 지식' 카테고리의 다른 글

C++ const(상수) 예약어  (0) 2024.02.21