포인터 연산에는 다음과 같은 네 가지 연산이 있습니다.
&) : 변수의 메모리 주소를 가져옴+, -) : 포인터의 주소를 이동함*) : 포인터가 가리키는 값을 참조 (역참조)->) : 구조체/클래스 포인터를 통해 멤버 변수에 접근#include 및 struct 선언#include <iostream>
using namespace std;
struct Player
{
int hp; // +0 (첫 번째 멤버 변수, 구조체의 시작 위치)
int damage; // +4 (hp 이후의 4바이트 위치)
};
iostream: 표준 입출력을 위한 라이브러리 포함using namespace std;: std::cout, std::endl을 간결하게 사용하기 위해 선언struct Player: hp와 damage라는 두 개의 int 멤버 변수를 가진 구조체hp는 구조체 시작 주소에 위치하며, damage는 hp 뒤의 +4바이트 위치에 저장됨main() 함수int main()
{
int number = 1;
number라는 4바이트 크기의 정수형 변수를 선언하고, 1로 초기화&)int* pointer = &number;
pointer는 number의 주소를 저장하는 포인터&number: number 변수의 주소를 가져옴int* pointer: 포인터가 int 타입의 데이터를 가리킨다는 의미📍 디버깅으로 확인할 수 있는 값
number = 1
&number = 0x1000 (가정, 메모리 주소)
pointer = 0x1000
+, -)number += 1; // number = 2;
number 값이 1 증가하여 2가 됨pointer += 1; // 포인터 이동 (4바이트 증가)
📍 여기서 중요한 개념
+1을 하면, 실제로 값이 1 증가하는 것이 아니라, 데이터 타입 크기만큼 주소가 증가합니다.pointer는 int*이므로 int 크기(4바이트)만큼 증가pointer += 1; 실행 시, pointer는 기존 주소보다 4바이트 증가한 주소를 가리킴📍 메모리 변화 예시 (32비트 시스템)
number = 2
pointer = 0x1000 → 0x1004 (4바이트 증가)
*)number = 3;
*pointer = 3;
*pointer = 3;은 pointer가 가리키는 주소에 있는 값을 3으로 변경하는 코드pointer는 0x1004를 가리키므로, 원래 number의 값은 변경되지 않음 (잘못된 접근 가능성 있음)📍 메모리 구조 예시
| 주소 | 값 | 변수명 |
|----------|----|------|
| 0x1000 | 2 | number |
| 0x1004 | 3 | (잘못된 메모리 접근) |
Player player;
player.hp = 100;
player.damage = 10;
Player 구조체 변수 player를 생성하고, hp와 damage 값을 설정Player* playerPtr = &player;
playerPtr 포인터가 player의 주소를 가리키도록 설정(*playerPtr).hp = 200;
(*playerPtr).damage = 200;
(*playerPtr).hp: playerPtr이 가리키는 player 구조체의 hp 값을 200으로 변경(*playerPtr).damage: playerPtr이 가리키는 player 구조체의 damage 값을 200으로 변경📍 메모리 구조 예시
| 주소 | 값 | 변수명 |
|----------|----|------|
| 0x2000 | 200 | player.hp |
| 0x2004 | 200 | player.damage |
->)playerPtr->hp = 200;
playerPtr->damage = 200;
(*playerPtr).hp = 200; 대신 playerPtr->hp = 200; 형태로 사용할 수 있음-> 연산자는 (*ptr).멤버 표현을 간소화한 문법✅ 둘은 동일한 의미
(*playerPtr).hp = 200;
playerPtr->hp = 200; // 동일한 코드
어셈블리 코드를 통해 포인터 연산이 어떻게 처리되는지 확인할 수 있습니다.
lea eax, [number] ; number 변수의 주소를 eax 레지스터에 저장
mov dword ptr [pointer], eax ; pointer 변수에 number 주소 저장
mov eax, dword ptr [pointer] ; pointer가 가리키는 값을 eax에 저장
mov dword ptr [eax], 3 ; eax가 가리키는 주소에 3 저장 (number = 3)
📍 어셈블리 분석
1. lea eax, [number] → number 변수의 주소를 eax 레지스터에 저장
2. mov dword ptr [pointer], eax → pointer 변수에 number의 주소 저장
3. mov eax, dword ptr [pointer] → pointer가 가리키는 주소의 값을 eax에 저장
4. mov dword ptr [eax], 3 → eax가 가리키는 주소에 3을 저장 (즉, number = 3)
| 연산자 | 설명 | 예제 |
|---|---|---|
& | 변수의 주소를 가져옴 | int* ptr = # |
+ / - | 포인터를 타입 크기만큼 이동 | ptr += 1; (4바이트 증가) |
* | 포인터가 가리키는 값을 참조 | *ptr = 10; |
-> | 구조체/클래스 멤버에 접근 | ptr->hp = 100; |
잘못된 메모리 접근
NULL이거나 초기화되지 않은 경우 런타임 오류 발생 가능int* ptr;
*ptr = 10; // 오류 발생 (ptr이 유효한 주소를 가리키지 않음)
메모리 누수 방지
delete 또는 free로 해제해야 함