All is well

[YYBASIC0301/얌얌코딩] 포인터 타입변수, 구조체 포인터 본문

C++/YYBASIC

[YYBASIC0301/얌얌코딩] 포인터 타입변수, 구조체 포인터

D0YUN 2025. 2. 9. 09:59

포인터 타입이란?

  • 포인터 변수는 메모리 주소를 저장하는 변수로, 메모리에 있는 데이터의 위치를 참조하는 역할을 합니다.
  • 변수고유한 메모리 주소를 가지며, 이를 통해 CPU해당 변수에 접근할 수 있습니다.
  • C++과 같은 언어에서는 개발자가 직접 메모리를 관리해야 하므로 주소 값을 저장할 수 있는 포인터 타입이 필요합니다.
  • `&`(주소 연산자)를 사용하면 변수의 메모리 주소를 가져올 수 있지만, 이 주소 값은 반드시 포인터 타입 변수에 저장해야 합니다.

포인터 변수와 배열의 효율적 활용

  • 포인터 변수를 사용하면 메모리의 주소값을 직접 관리할 수 있어 불필요한 복사 연산을 줄일 수 있습니다.
    • 배열을 복사할 때마다 새로운 메모리 공간을 할당해야 하지만, 포인터를 사용하면 주소값만 전달하여 메모리 사용량을 줄일 수 있습니다.
  • 데이터 크기가 크거나 복잡한 경우, 포인터를 사용하면 메모리 사용이 효율적이며 연산 속도가 빨라집니다.
  • `*`연산자를 이용하면 포인터가 가리키는 주소에 직접 접근하여 값을 조회하거나 변경할 수 있습니다.
  • 즉, 변수를 직접 복사하지 않고 주소를 통해 값을 다루므로 깊은 복사(Deep Copy)를 피하고, 얕은 복사(Shallow Copy) 방식으로 동작합니다.
  • 포인터는 배열처럼 사용할 수도 있어 친숙한 배열 접근 방식으로 데이터를 다룰 수 있습니다.

cf) `*` 연산자의 다양한 쓰임

// * 연산자의 용도

#include <iostream>
using namespace std;

int main() {
    // 1. 곱셈 연산자로 사용
    int a = 5, b = 10;
    int result = a * b; // 곱셈 연산
    cout << "곱셈 결과: " << result << endl; // 50 출력

    // 2. 포인터 선언 및 사용
    int num = 20;
    int *ptr = &num; // 포인터 선언 및 주소 저장

    cout << "변수 num의 값: " << num << endl;      // 20 출력
    cout << "포인터 ptr이 가리키는 값: " << *ptr << endl; // 20 출력 (역참조)

    // 3. 포인터를 이용한 메모리 값 변경
    *ptr = 30; // 포인터를 통해 변수 num의 값을 변경
    cout << "포인터를 이용해 변경된 num의 값: " << num << endl; // 30 출력

    return 0;
}
  • 이항 연산자로의 사용 : 곱셉 연산자로 쓰입니다.
  • 포인터 선언에 사용됩니다.
  • 메모리 접근에 사용됩니다.

포인터와 구조체의 활용

  • `->` (화살표 연산자)를 사용하면 포인터를 통해 구조체 멤버에 접근하는 과정이 간결해집니다.
  • 구조체와 클래스를 포인터로 다루면, 객체를 직접 복사하지 않고 주소를 이용하여 효율적으로 접근할 수 있습니다.
  • 구조체를 사용하면 코드의 유지보수성과 확장성이 증가하며, 여러 개의 데이터를 한 번에 다룰 수 있어 가독성이 좋아집니다.

✅ 구조체 사용의 장점

✔ 여러 개의 데이터를 하나로 묶어 효율적으로 관리할 수 있습니다.

✔ 새로운 속성을 추가할 때 기존 코드를 수정할 필요 없이 확장 가능합니다.

❌ 구조체 사용의 단점

메모리를 더 많이 사용할 수 있습니다.

✖ 일반 변수보다 접근 방식이 다소 복잡할 수 있습니다.

구조체 포인터의 장점

  • 구조체를 포인터로 사용하면 메모리 낭비 없이 효율적으로 데이터를 관리할 수 있습니다.
  • 게임 개발을 예로 들면, 플레이어의 HP를 저장하는 변수뿐만 아니라, 공격력, 방어력 등의 속성을 추가할 경우 구조체가 유용합니다.
    • 구조체를 사용하면 기존 코드를 수정하지 않고도 새로운 속성을 쉽게 추가할 수 있어 유지보수가 편리합니다.
// YYBASIC03_01

#include <iostream>
using namespace std;

int main(void)
{
    /* 포인터 타입 복습 */
    #pragma region 포인터 타입에 대하여
    // 포인터 : 주소값을 저장할 수 있는 타입

    unsigned int addrNum = 0;
    // 주소 : 숫자이므로 int로 저장해도 무방

    int a = 0;
    addrNum = (unsigned int)&a;

    // 포인터 변수 앞에 *을 붙이면
    // 해당 주소에 있는 변수(위치)로 이동
    // 또는 가리킨다고 함
    #pragma endregion

    
    #pragma region 구조체 포인터
    struct Vector2
    {
        int x, y;
    };

    Vector2 p1;
    Vector2* vp = &p1;     // Vector2 타입 포인터

    (*vp).x = 100;
    (*vp).y = 100;

    //*vp.x = 200;   // ERROR
    //*(vp.x) = 200;
    // . 연산자가  * 연산자보다 우선순위가 높아
    // 구조체 변수에 제대로 접근할 수 없다
    #pragma endregion


    #pragma region -> 포인터 연산자
    vp->x = 200;    // 다음과 같다 - (*vp).x = 200;
    vp->y = 200;
    #pragma endregion


    #pragma region 구조체 이용의 장점
    // : 추가 확장이 매우 편리해진다 - 유지보수성이 높아진다
    struct Status
    {
        int hp;
        //int mp;
    };

    Status stat;
    stat.hp = 100;
    //stat.mp = 100;
    #pragma endregion

    return 0;
}

 

 

https://www.youtube.com/watch?v=wVIGmqSroJ0