4-1. 포인터

Crat3 ㅣ 2023. 5. 11. 15:45

0. 포인터의 필요성

 

(1) 변수

int number = 1;

- 4바이트 정수 타입의 number 변수

- 스택 메모리에 할당됨

- 스택 메모리의 특정 주소(number에 해당하는 주소)에 우리가 원하는 값인 1을 대입

- 즉 특정 메모리에 number라는 이름을 붙인 것과 같다

 

* 단점

- 전역 변수가 아닌 지역 변수는 외부에서 접근할 수 없음

=> 따라서 포인터를 사용하여 이를 해결할 수 있음

 

1. 포인터

 

(1) 정의

//TYPE* 변수이름;
int* ptr;

메모리의 주소를 저장하는 역할을 한다.

ex) 변수 선언 시 '*'가 붙어있다 -> 포인터이다 -> 주소 값을 갖고 있다

int number = 1;

int main()
{
    int* ptr = &number; // &number는 number의 주소
    return 0;
}

위와 같은 코드로 ptr에 number의 주소를 저장한다.

이때 포인터는 4바이트(32비트) 혹은 8바이트(64비트)로 (시스템에 따라) 고정됨.

 

(2) 사용

포인터가 가리키는 주소로 가서 값을 수정할 수 있다.

*변수이름 = 값;
int main()
{
    int* ptr = &number;

    int value1 = *ptr;  // value1에 ptr에 저장된 주소의 값을 저장함
    *ptr = 2;		// ptr에 저장된 주소의 값에 2를 대입함

    return 0;
}

즉 '*ptr'은 해당 주소의 값을 뜻한다.

 

(3) TYPE을 붙이는 이유?

int* ptr = &number;

포인터는 항상 8바이트 혹은 16바이트인데,

위의 코드에서 int와 같이 타입을 붙이는 이유가 뭘까?

=> 해당 주소의 값이 어떤 형식인지 알아야 몇 바이트 까지가 그 주소의 값인지 알 수 있기 때문!!

 

(4) TYPE의 불일치

int main()
{
    __int64* ptr2 = (__int64*)&number;
    *ptr2 = 0xAABBCCDDEEFF;

    return 0;
}

number는 4바이트 정수가 저장되어 있다. 그런데 ptr2를 강제로 8바이트 정수로 지정하고 주소를 저장하고 값을 변경해 주면

다른 메모리의 영역을 침범해서 값을 덮어씌워 버릴 수 있다.

 

(5) 활용

광역 변수와 지역 변수의 이름이 동일하면 함수 내에서 사용 시 광역변수의 값을 우선적으로 사용한다.

void SetHp(int hp)
{
    hp = 100;
}

int main()
{
    int hp = 1;
    SetHp(hp); // SetHp(100);

    return 0;
}

이 문제를 해결하기 위해 포인터를 사용할 수 있다.

void SetHp(int* hp)
{
    *hp = 100;
}

int main()
{
    int hp = 1;
    SetHp(&hp); //매개변수(주소)

    return 0;
}

즉 지역 변수 hp의 값을 100으로 수정할 수 있다.

'기초 C++ 스터디' 카테고리의 다른 글

4-4. 참조  (0) 2023.05.11
4-2. 포인터 연산  (0) 2023.05.11
3-7. 구조체  (0) 2023.05.10
3-5. 함수 오버로드, 기본 인자값, 스택 오버플로우  (0) 2023.05.09
3-4. 호출 스택  (0) 2023.05.09