전체 코드


🔹 1. 코드 개요

이 코드는 플레이어와 몬스터의 전투를 시뮬레이션하는 프로그램으로, 다음과 같은 기능을 포함합니다.

  1. 로비 입장 (EnterLobby())
  2. 플레이어 생성 (CreatePlayer())
  3. 몬스터 생성 (CreateMonster())
  4. 전투 실행 (StartBattle())
  5. 승리 또는 패배 출력

포인터를 사용하여 플레이어와 몬스터의 정보를 전달 및 수정하고, 포인터를 사용하지 않은 경우와 비교하여 구조체 복사의 오버헤드를 확인할 수 있습니다.


🔹 2. 코드 분석 및 상세 설명

📌 2.1 구조체 정의 (StatInfo)

struct StatInfo {
    int hp;       // +0 (체력)
    int attack;   // +4 (공격력)
    int defence;  // +8 (방어력)
};
  • hp, attack, defence 세 개의 멤버 변수를 포함하는 구조체 StatInfo를 정의합니다.
  • 메모리에서 순차적으로 배치됩니다. (hp는 0번 오프셋, attack은 +4, defence는 +8)

📍 메모리 구조 예시 (32비트 시스템)
| 주소 | 변수명 | 크기 |
|----|-----|----|
| 0x1000 | hp | 4바이트 |
| 0x1004 | attack | 4바이트 |
| 0x1008 | defence | 4바이트 |


📌 2.2 함수 선언

void EnterLobby();  // 로비에 입장
StatInfo CreatePlayer();  // 플레이어 생성 (구조체 반환)
void CreateMonster(StatInfo* info);  // 몬스터 생성 (포인터로 데이터 수정)
bool StartBattle(StatInfo* player, StatInfo* monster);  // 전투 실행
  • CreatePlayer()는 구조체를 복사하여 반환.
  • CreateMonster()포인터를 사용하여 직접 값을 변경.
  • StartBattle()플레이어와 몬스터 포인터를 전달받아 전투를 진행.

📌 2.3 main() 함수

int main() {
    EnterLobby();
    return 0;
}
  • EnterLobby() 호출을 통해 게임을 시작합니다.

📌 2.4 EnterLobby() 함수

void EnterLobby() {
    cout << "로비에 입장했습니다." << endl;
  • 로비 입장 메시지를 출력.
    StatInfo player;
    player.hp = 0xbbbbbbbb;
    player.attack = 0xbbbbbbbb;
    player.defence = 0xbbbbbbbb;
  • player 변수를 선언하고 초기값을 임의의 값(0xbbbbbbbb)으로 설정.
  • 이후 CreatePlayer() 호출을 통해 실제 값을 덮어씌웁니다.
    player = CreatePlayer();
  • CreatePlayer()가 반환한 구조체를 복사하여 player에 저장.
  • 구조체 복사 발생 → 내부적으로 hp, attack, defence 값이 하나씩 복사됨.

📍 구조체 복사 과정 (비효율적인 방식)

player.hp = ret.hp;
player.attack = ret.attack;
player.defence = ret.defence;

이런 방식은 불필요한 메모리 복사를 발생시킴!


📌 2.5 몬스터 생성 (CreateMonster 사용)

    StatInfo monster;
    monster.hp = 0xbbbbbbbb;
    monster.attack = 0xbbbbbbbb;
    monster.defence = 0xbbbbbbbb;
  • monster 구조체를 선언하고, 임시 초기값을 설정.
    CreateMonster(&monster);
  • CreateMonster() 함수에 monster의 주소를 전달하여, 구조체를 복사하지 않고 직접 수정.

📍 포인터를 사용한 구조체 수정의 장점

void CreateMonster(StatInfo* info) {
    info->hp = 40;
    info->attack = 8;
    info->defence = 1;
}
  • 메모리 복사가 발생하지 않음 (주소를 통해 직접 수정).

📌 2.6 구조체 복사 테스트

    player = monster;

📍 구조체 복사 시 발생하는 내부 동작

player.hp = monster.hp;
player.attack = monster.attack;
player.defence = monster.defence;
  • 내부적으로 3번의 데이터 복사가 발생.
  • 구조체 크기가 커질수록 비효율적!
  • 포인터를 사용하면 이런 복사를 피할 수 있음.

📌 2.7 전투 시작 (StartBattle)

    bool victory = StartBattle(&player, &monster);
  • playermonster주소를 전달하여 원본 값을 직접 수정.

📍 메모리 변화를 고려한 방식

void StartBattle(StatInfo* player, StatInfo* monster);

➡ 포인터를 사용하여 원본 구조체를 수정하면 복사 비용이 발생하지 않음.


📌 2.8 전투 (StartBattle 함수)

bool StartBattle(StatInfo* player, StatInfo* monster) {
    while (true) {
        int damage = player->attack - monster->defence;
        if (damage < 0)
            damage = 0;
        monster->hp -= damage;
  • 플레이어가 몬스터를 공격. (player->attack - monster->defence 만큼 HP 감소)
        cout << "몬스터 HP : " << monster->hp << endl;
        if (monster->hp == 0)
            return true;
  • 몬스터의 HP가 0이면 플레이어 승리.
        damage = monster->attack - player->defence;
        if (damage < 0)
            damage = 0;
        player->hp -= damage;
  • 몬스터가 플레이어를 공격.
        cout << "플레이어 HP : " << player->hp << endl;
        if (player->hp == 0)
            return false;
    }
}
  • 플레이어의 HP가 0이면 몬스터 승리.

🔹 3. 포인터 사용의 장점

  1. 구조체 복사 비용 절약

    • CreatePlayer()복사본을 반환하지만, CreateMonster()포인터를 통해 원본을 수정.
    • 구조체 크기가 클수록 포인터를 활용하는 것이 성능상 유리.
  2. 메모리 사용 최적화

    • 구조체를 복사하지 않고 주소를 직접 전달하여 수정.
  3. 포인터를 활용한 구조체 수정

    • -> 연산자를 사용하여 구조체의 멤버에 직접 접근 (info->hp).

profile
李家네_공부방

0개의 댓글