ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2024.02.27 - 포인터
    C++ 2024. 2. 27. 18:10

     

    • 포인터가 무엇인가

    포인터(포인터 변수)는 기본적으로 주소를 저장하는 변수다.

    우리가 기존에 써왔던 변수는 데이터를 저장하는 변수지만, 포인터는 메모리의 주소를 저장하는 변수다.

     

    • 포인터는 어떻게 쓰는가
    int* ptr;
    //int *ptr;

    int형 변수의 주소를 저장하는 포인터(포인터 변수) ptr을 만들었다.

    아래처럼 써도 무방하지만, 포인터 변수를 생성할 때와, 나중에 나올 포인터 변수로 역참조를 할때가 헷갈릴 수 있으므로, 위의 방식처럼 사용하도록 하자.

     

    • 포인터에 값을 넣어보자
    int num = 10;
    int* ptr = #

    포인터에는 일반적인 데이터를 저장할 수 없고, 오로지 주소값만 저장할 수 있다.

    &연산자를 이용해서 num변수의 주소값을 포인터 ptr에 저장했다.

     

    • 포인터가 실제로 무슨 값을 가졌는지 출력을 통해 확인해보자
    #include<iostream>
    
    int main() {
        int number = 10;
        int* ptr = &number;
    
        std::cout << "변수 number의 값: " << number << std::endl;
        std::cout << "변수 number의 주소값: " << &number << std::endl;
        std::cout << "포인터 변수 ptr의 값: " << ptr << std::endl;
    }

    포인터에 num의 주소값인 &num을 대입해서 &num과 같은값을 가지게 되었다.

    그래서 포인터로 뭐 할라고 저렇게 주소값을 넣는걸까?

     

    • 포인터와 역참조를 통해서 주소값 자리에 있는 값을 구하기
    #include<iostream>
    
    int main() {
        int number = 10;
        int* ptr = &number;
    
        std::cout << "변수 number의 값: " << number << std::endl;
        std::cout << "변수 number의 주소값: " << &number << std::endl;
        std::cout << "포인터 변수 ptr의 값: " << ptr << std::endl;
        std::cout << "포인터 변수 ptr이 가리키는 값: " << *ptr << std::endl;   //역참조
    }

    포인터에 *을 씌워 *안의 포인터에 저장된 주소값이 가리키는 메모리에 있는 값을 불러올 수 있다.

    *(포인터) 처럼 괄호로 씌워도 된다.

    그런데 number값이 필요하면 그냥 number를 불러오면 되는거 아닌가?

    왜 포인터를 통해 number값을 전달 받으려고 하는 걸까?

     

    어떤 변수 값을 넘기려고 할때 그냥 변수를 넘기면 해당 변수의 크기만큼 데이터가 복사된다. 포인터를 통해 변수를 전달하는 경우, 포인터를 넘기면 포인터 변수의 크기만큼만 데이터가 복사된다. 최적화에 엄청 도움이 된다.

     

    • 역참조로 변수 값 접근하기
    #include<iostream>
    
    int main() {
        int num = 9;
        std::cout << "num의 값: " << num << std::endl;
        std::cout << "num의 주소값: " << &num << std::endl;
    
        int* p = &num;
        std::cout << "p의 값: " << p << std::endl;
        std::cout << "p가 가리키는 값(num): " << *p << std::endl;
    
        //역참조를 통해서 포인터가 가리키는 변수값을 바꿀 수 있다.
        *p = 777;
        std::cout << "바꾼 후 p가 가리키는 값(num): " << *p << std::endl;
    }

     

    • 더블 포인터

    포인터(포인터 변수)도 주소 값을 가지기 때문에, 포인터의 포인터도, 포인터의 포인터의 포인터도 가능하다.

    복잡하지만 포인터가 동작하는 방식을 이해하고 있으면 중첩해서 사용할 수 있다. 

    #include<iostream>
    
    int main() {
        int num = 9;
        std::cout << "num의 값: " << num << std::endl;
        std::cout << "num의 주소값: " << &num << std::endl;
    
        int* p = &num;
        std::cout << "p의 값: " << p << std::endl;
        //포인터 변수도 변수니까 주소값을 가지고 있다.
        std::cout << "p의 주소값: " << &p << std::endl;
        std::cout << "p가 가리키는 값(num): " << *p << std::endl;
    
        //더블 포인터
        int** pp;
        //pp = &num; //더블 포인터도 주소값을 가지지만, 일반 변수의 주소값을 가질 수는 없다. (에러뜸)
        pp = &p; //더블 포인터는 포인터 변수의 주소를 가진다. 
        std::cout << "pp가 가리키는 값(포인터 변수 p의 주소값): " << pp << std::endl;
        std::cout << "pp를 역참조하면? p의 값을 주겠지? *pp = " << *pp << std::endl;
        std::cout << "pp를 두번 역참조하면? num의 값을 주겠지? **pp = " << **pp << std::endl;
    }

     

Designed by Tistory.