'포인터 = 주소' 라고 생각하자.
기존 변수들(int, float 등)이 값을 저장하는 바구니라면, 포인터는 주소를 저장하는 바구니다.
기본적인 형식
int number = 1;
// ptr은 number의 주소를 가리키게 된다.
int* ptr = &number;
// ※아래 주소값들은 컴퓨터 환경마다, 실행할 때마다 달라질 수 있다.
// ptr의 주소 = 0x008FFE64, ptr의 값(number의 주소) = 008ffe70
// number의 주소 = 0x008FFE70, number의 값 = 1
*
: 사용 시점에 따라서 구분해서 기억하자. int* ptr = &number;
// value1에 ptr이 가리키고 있는(number=1) 변수의 값을 넣어라!
int value1 = *ptr;
// number의 값을 2로 바꿔라!
*ptr = 2;
// [ 매개변수(hp의 주소) ][ RET ][ 지역변수 ]
// void SetHp(int* hp) --> void SetHP(hp의 주소)
void SetHp(int* hp)
{
// *hp --> hp의 주소로 이동해라.(순간이동)
*hp = 100;
}
int main()
{
int hp = 10;
cout << hp << endl; // hp = 10
SetHp(&hp);
cout << hp << endl; // hp = 100
}
포인터라는 바구니는 4byte or 8byte 고정 크기이다.
(운영체제가 32bit인지 64bit인지에 따라 다르다.)
고정크기인 이유? -> 결국은 주소를 담고 있기 때문.
그럼 int*
처럼 포인터가 어떤 자료형을 가리키는지 명시해줄 필요가 없는거 아닌가?
주의) 타입의 불일치
number 는 int
형(4byte 정수)인데, __int64
형(8byte 정수)로 캐스팅 한다면?
다른 메모리 주소를 침범하여 값을 덮어쓰게 된다. -> 데이터가 오염된다.
__int64* ptr2 = (__int64*)&number;
// AABB CCDDEEFF -> AABB가 다른 메모리 주소에 쓰여진다.
*ptr2 = 0xAABBCCDDEEFF;
__int64* ptr2 = (__int64*)&number;
에 브레이크 포인트를 걸고 디버깅한 모습.
*ptr2 = 0xAABBCCDDEEFF;
까지 실행하고 디버깅한 모습.