포인터의 기본

Jaemyeong Lee·2024년 8월 7일
0

FastCampusC++

목록 보기
30/78

C++ 포인터 기본 개념과 사용법

포인터는 C++에서 매우 중요한 개념 중 하나입니다. 포인터를 사용하면 변수의 주소를 직접 다루고, 메모리 관리와 데이터 구조를 효율적으로 조작할 수 있습니다. 이번 포스트에서는 포인터의 기본 개념과 다양한 사용법을 예제와 함께 살펴보겠습니다.

1. 포인터 기본 개념

포인터는 변수의 주소를 저장하는 변수입니다. 다음 예제에서는 기본적인 포인터 사용법을 보여줍니다.

#include <iostream>

using namespace std;

int main()
{
    int num = 100; // 정수형 변수 num을 선언하고 100으로 초기화

    int* pointer = &num; // 정수형 포인터 pointer를 선언하고 num의 주소값을 저장

    cout << "num의 값: " << num << endl; // num의 값 출력
    cout << "num의 주소값: " << &num << endl; // num의 주소값 출력
    cout << "pointer의 값(주소): " << pointer << endl; // pointer가 가리키는 주소 출력

    cout << "pointer가 가리키는 값: " << *pointer << endl; // 포인터 역참조, pointer가 가리키는 값 출력
    *pointer = 200; // pointer가 가리키는 값에 200을 대입

    cout << "num의 새로운 값: " << num << endl; // num의 값 출력
    cout << "pointer가 가리키는 새로운 값: " << *pointer << endl; // pointer가 가리키는 값 출력

    return 0;
}

위 코드에서 pointernum의 주소를 저장하고, *pointernum의 값을 참조합니다. 포인터를 통해 num의 값을 변경할 수도 있습니다.

2. 여러 포인터가 같은 변수를 가리킬 때

여러 포인터가 같은 변수를 가리킬 수 있습니다. 다음 예제를 통해 살펴보겠습니다.

#include <iostream>

using namespace std;

int main()
{
    int num = 123; // 정수형 변수 num을 선언하고 123으로 초기화
    int* pNum0 = &num; // pNum0 포인터에 num의 주소값을 저장
    int* pNum1 = &num; // pNum1 포인터에 num의 주소값을 저장
    int* pNum2 = pNum0; // pNum2 포인터에 pNum0의 주소값을 저장

    cout << "num의 주소값: " << &num << endl;
    cout << "pNum0의 값(주소): " << pNum0 << endl;
    cout << "pNum1의 값(주소): " << pNum1 << endl;
    cout << "pNum2의 값(주소): " << pNum2 << endl;

    cout << "num의 값: " << num << endl;
    cout << "pNum0가 가리키는 값: " << *pNum0 << endl;
    cout << "pNum1가 가리키는 값: " << *pNum1 << endl;
    cout << "pNum2가 가리키는 값: " << *pNum2 << endl;

    num = 100; // num에 100을 대입
    cout << "num의 새로운 값: " << num << endl;
    cout << "pNum0가 가리키는 새로운 값: " << *pNum0 << endl;
    cout << "pNum1가 가리키는 새로운 값: " << *pNum1 << endl;
    cout << "pNum2가 가리키는 새로운 값: " << *pNum2 << endl;

    return 0;
}

위 코드에서 pNum0, pNum1, pNum2는 모두 num의 주소를 가리키며, num의 값이 변경되면 세 포인터가 가리키는 값도 변경됩니다.

3. 널 포인터

널 포인터는 어떤 것도 가리키지 않는 포인터입니다. 초기화되지 않은 포인터를 사용하면 정의되지 않은 동작이 발생할 수 있습니다.

#include <iostream>

using namespace std;

int main()
{
    int* pNum = 0; // 정수형 포인터 pNum을 널 포인터로 초기화
    cout << "pNum의 값: " << pNum << endl; // 0 출력
    // cout << *pNum << endl; // 주석 처리됨, 정의되지 않은 동작 발생

    return 0;
}

널 포인터를 사용하면 프로그램의 안정성을 높일 수 있습니다.

4. 유니언과 포인터

유니언은 여러 데이터 타입을 하나의 메모리 공간에서 공유할 수 있도록 합니다. 포인터를 사용하여 유니언을 다양한 타입으로 해석할 수 있습니다.

#include <iostream>

using namespace std;

union Union
{
    int i;
    float f;
    double d;
};

int main()
{
    Union u; // 유니언 u 선언
    int* ip = (int*)&u; // u의 주소를 정수형 포인터로 캐스팅하여 저장
    float* fp = (float*)&u; // u의 주소를 실수형 포인터로 캐스팅하여 저장
    double* dp = (double*)&u; // u의 주소를 더블형 포인터로 캐스팅하여 저장

    u.i = 1; // u의 int 멤버에 1을 대입

    cout << "u의 int 값: " << u.i << endl; // 1 출력
    cout << "ip가 가리키는 값: " << *ip << endl; // 1 출력

    cout << "u의 float 값: " << u.f << endl;
    cout << "fp가 가리키는 값: " << *fp << endl;

    cout << "u의 double 값: " << u.d << endl;
    cout << "dp가 가리키는 값: " << *dp << endl;

    return 0;
}

위 예제에서 유니언 u는 하나의 메모리 공간을 여러 타입으로 해석할 수 있습니다.

5. const 포인터

포인터를 상수로 선언하여 포인터가 가리키는 값이나 포인터 자체를 변경하지 못하게 할 수 있습니다.

5.1. 값 변경 불가능한 포인터

#include <iostream>

using namespace std;

int main()
{
    int num0 = 10; // 정수형 변수 num0을 선언하고 10으로 초기화
    const int* pNum = &num0; // const int 포인터 pNum을 선언하고 num0의 주소를 저장

    int num1 = 20; // 정수형 변수 num1을 선언하고 20으로 초기화
    pNum = &num1; // 가능, pNum이 가리키는 주소 변경

    // *pNum = 30; // 불가능, 주석 처리됨, 가리키는 값을 변경할 수 없음

    return 0;
}

위 예제에서 pNum은 가리키는 값을 변경할 수 없습니다. 하지만 가리키는 주소는 변경할 수 있습니다.

5.2. 주소 변경 불가능한 포인터

#include <iostream>

using namespace std;

int main()
{
    int num0 = 10; // 정수형 변수 num0을 선언하고 10으로 초기화
    int* const pNum = &num0; // 상수 포인터 pNum 선언, num0의 주소를 저장

    int num1 = 20; // 정수형 변수 num1을 선언하고 20으로 초기화
    // pNum = &num1; // 불가능, 주석 처리됨, 상수 포인터가 가리키는 주소는 변경 불가

    *pNum = 30; // 가능, 포인터가 가리키는 값을 변경

    return 0;
}

위 예제에서 pNum은 가리키는 주소를 변경할 수 없습니다. 하지만 가리키는 값은 변경할 수 있습니다.

5.3. 이중 const 포인터

#include <iostream>

using namespace std;

int main()
{
    int num0 = 10; // 정수형 변수 num0을 선언하고 10으로 초기화
    const int* const pNum = &num0; // 이중 상수 포인터 pNum 선언, num0의 주소를 저장

    int num1 = 20; // 정수형 변수 num1을 선언하고 20으로 초기화
    // pNum = &num1; // 불가능, 주석 처리됨, 포인터가 가리키는 주소 변경 불가
    // *pNum = 30; // 불가능, 주석 처리됨, 포인터가 가리키는 값 변경 불가

    return 0;
}

위 예제에서 pNum은 가리키는 주소와 값을 모두 변경할 수 없습니다.

profile
李家네_공부방

0개의 댓글