본문 바로가기
개발이야기/언리얼 c++

언리얼 C++ : typedef와 typedef struct는 왜 사용하는 걸까?

by oddsilk 2024. 5. 24.

typedef는 C와 C++에서 데이터 타입에 새로운 이름을 부여하는 키워드입니다. typedef는 코드의 가독성을 높이고, 복잡한 데이터 타입을 간단하게 표현하는 데 유용합니다. 특히 구조체(struct)를 사용할 때 자주 사용되는데, 그 이유와 함께 자세히 설명하겠습니다.

왜 typedef를 사용하는가?

  1. 가독성 향상:
    • 복잡한 타입을 간단한 이름으로 바꿔서 코드가 더 읽기 쉽고 이해하기 쉽게 만듭니다.
  2. 유지보수 용이성:
    • 데이터 타입이 변경되었을 때, typedef를 사용하면 변경된 타입을 정의한 한 곳만 수정하면 되므로 유지보수가 쉬워집니다.
  3. 코드 일관성:
    • 같은 타입을 여러 곳에서 사용할 때, typedef를 통해 일관된 이름을 사용할 수 있습니다.

왜 typedef struct를 자주 사용하는가?

C에서는 구조체를 선언하고 사용할 때 매번 struct 키워드를 사용해야 합니다. 하지만 typedef struct를 사용하면 구조체의 이름을 간단히 사용할 수 있습니다. 다음 예시를 통해 설명하겠습니다.

 

 

예시

typedef 없이 구조체 사용

 

struct Point {
    int x;
    int y;
};

int main() {
    struct Point p1;
    p1.x = 10;
    p1.y = 20;
    return 0;
}

 

위 코드에서, 구조체 변수를 선언할 때마다 struct Point를 사용해야 합니다.

typedef를 사용한 구조체

// typedef를 사용하여 새로운 타입 이름을 정의합니다.
// 이 경우 struct Point를 Point라는 새로운 이름으로 정의합니다.
typedef struct {
    int x; // x 좌표
    int y; // y 좌표
} Point;

int main() {
    // 이제 struct Point 대신 Point를 사용할 수 있습니다.
    Point p1;
    p1.x = 10; // p1의 x 값을 10으로 설정
    p1.y = 20; // p1의 y 값을 20으로 설정
    return 0;
}

위 코드에서는 Point라는 타입 이름만 사용하면 되므로 더 간단하고 읽기 쉬워집니다.

typedef의 일반적인 사용 예시

1) 기본 타입에 새로운 이름 부여

typedef unsigned long ulong;

ulong largeNumber = 1000000; // unsigned long 대신 ulong 사용

 

2) 함수 포인터에 이름 부여

typedef void (*Callback)(int);

void myFunction(Callback cb) {
    cb(42); // 콜백 함수 호출
}

void printNumber(int num) {
    printf("Number: %d\n", num);
}

int main() {
    myFunction(printNumber); // 함수 포인터로 printNumber 전달
    return 0;
}

언리얼 소스코드에서 자주 보이는 형태

소스 코드에서 typedef가 사용된 예시를 보면, typedef는 다양한 데이터 타입에 새로운 이름을 부여하여 코드의 가독성을 높이고, 코드 작성이 더 간편하도록 도와주는 역할을 합니다. 주어진 코드에서 typedef의 역할과 의미를 하나씩 살펴보겠습니다.

// void* 타입을 HANDLE이라는 이름으로 정의합니다. HANDLE은 주로 윈도우에서 객체를 가리키는 포인터로 사용됩니다.
typedef void* HANDLE;

// HINSTANCE__ 타입의 포인터를 HINSTANCE라는 이름으로 정의합니다. HINSTANCE는 윈도우 애플리케이션의 인스턴스를 나타냅니다.
typedef HINSTANCE__* HINSTANCE;

// HINSTANCE와 HMODULE은 동일한 타입으로, 모듈 핸들을 나타냅니다.
typedef HINSTANCE HMODULE;

// HWND__ 타입의 포인터를 HWND라는 이름으로 정의합니다. HWND는 윈도우 핸들을 나타냅니다.
typedef HWND__* HWND;

// HKEY__ 타입의 포인터를 HKEY라는 이름으로 정의합니다. HKEY는 레지스트리 키 핸들을 나타냅니다.
typedef HKEY__* HKEY;

// HDC__ 타입의 포인터를 HDC라는 이름으로 정의합니다. HDC는 디바이스 컨텍스트 핸들을 나타냅니다.
typedef HDC__* HDC;

// HICON__ 타입의 포인터를 HICON이라는 이름으로 정의합니다. HICON은 아이콘 핸들을 나타냅니다.
typedef HICON__* HICON;

// HICON__ 타입의 포인터를 HCURSOR라는 이름으로도 정의합니다. HCURSOR는 커서 핸들을 나타냅니다.
typedef HICON__* HCURSOR;

// tagPROCESSENTRY32W 타입을 PROCESSENTRY32라는 이름으로 정의합니다. PROCESSENTRY32는 프로세스 정보를 나타냅니다.
typedef tagPROCESSENTRY32W PROCESSENTRY32;

// _EXCEPTION_POINTERS 타입의 포인터를 LPEXCEPTION_POINTERS라는 이름으로 정의합니다. LPEXCEPTION_POINTERS는 예외 정보를 나타냅니다.
typedef _EXCEPTION_POINTERS* LPEXCEPTION_POINTERS;

// _RTL_CRITICAL_SECTION 타입의 포인터를 LPCRITICAL_SECTION라는 이름으로 정의합니다. LPCRITICAL_SECTION는 임계 구역을 나타냅니다.
typedef _RTL_CRITICAL_SECTION* LPCRITICAL_SECTION;

// _OVERLAPPED 타입의 포인터를 LPOVERLAPPED라는 이름으로 정의합니다. LPOVERLAPPED는 오버랩 I/O 작업을 나타냅니다.
typedef _OVERLAPPED* LPOVERLAPPED;

// _LARGE_INTEGER 타입의 포인터를 LPLARGE_INTEGER라는 이름으로 정의합니다. LPLARGE_INTEGER는 큰 정수 값을 나타냅니다.
typedef _LARGE_INTEGER* LPLARGE_INTEGER;
typedef는 주어진 타입에 새로운 이름을 부여하는 키워드입니다. 이를 통해 코드의 가독성을 높이고, 특정 타입을 더 간편하게 사용할 수 있게 합니다. 특히 구조체나 포인터와 같은 복잡한 타입을 정의할 때 유용합니다. typedef struct를 자주 사용하는 이유는 구조체를 정의하고 사용할 때 더 간편하고 명확하게 만들기 위해서입니다.


결론

typedef는 복잡한 데이터 타입에 새로운 이름을 부여하여 코드의 가독성과 유지보수성을 높이는 데 유용합니다. 특히 구조체와 같은 복잡한 타입을 간단하게 사용할 수 있게 해줍니다. 따라서 typedef struct는 구조체를 사용할 때 매번 struct 키워드를 사용하지 않아도 되도록 만들어 코드가 더 깔끔하고 명확하게 작성될 수 있도록 돕습니다.