typedef 지정자

typedef 지정자

typedef는 (아마 복잡할) 타입 이름 대신 아무 데서나 쓸 수 있는 별명을 만들어 주는 지정자예요. "이 타입이 너무 길어서 매번 적기 힘들다" 싶을 때, 그리고 코드 어디에서든 그 타입을 가리키는 짧은 이름이 필요할 때 쓰죠. 여기서는 typedef가 정확히 어떤 선언을 만드는지, 그리고 어디에 쓰면 안 되는지까지 규칙 기준으로 정리해 볼게요.

출처: cppreference

본문

설명

typedef 지정자는 선언 안에서 쓰일 때, 그 선언을 변수나 함수 선언이 아니라 typedef 선언으로 만드는 역할을 해요.

typedef는 보통 선언의 맨 앞에 쓰지만, 타입 지정자 뒤나 두 타입 지정자 사이에 붙어도 허용돼요. 다만 타입 지정자 외에 다른 지정자는 함께 쓸 수 없어요.

typedef 선언은 한 줄에 여러 식별자를 선언할 수 있어요(예: intint에 대한 포인터). 배열·함수 타입, 포인터·참조, 클래스 타입 등도 선언할 수 있죠. 이 선언에서 도입된 모든 식별자는 typedef 이름이 되는데, 그 이름은 typedef 키워드를 뗐을 때 그 자리에 오게 될 객체나 함수의 타입과 같은 뜻의 별명이에요.

typedef 이름은 기존 타입의 별명이지, 새 타입을 선언하는 게 아니에요. typedef로 기존 타입 이름(typedef 이름 포함)의 의미를 바꿀 수는 없어요. 한 번 선언된 typedef 이름은 같은 타입을 다시 가리킬 때만 다시 선언될 수 있어요. typedef 이름은 보이는 스코프 안에서만 효력을 가지므로, 서로 다른 함수나 클래스에 같은 이름의 타입이 다른 뜻으로 정의될 수 있어요.

typedef 지정자는 함수 매개변수 선언이나 함수 정의의 decl-specifier-seq에는 들어갈 수 없어요.

void f1(typedef int param); // ill-formed
typedef int f2() {}         // ill-formed

또한 선언자가 없는 선언에도 typedef를 쓸 수 없어요.

typedef struct X {}; // ill-formed

링키지를 위한 typedef 이름 (typedef name for linkage purposes)

typedef 선언이 익명 클래스나 익명 열거형을 정의한다면, 그 선언이 만든 클래스 타입·열거형 타입의 첫 번째 typedef 이름이 바로 그 타입의 "링키지를 위한 typedef 이름"이 돼요.

예를 들어 typedef struct { /* ... */ } S;에서 S가 링키지를 위한 typedef 이름이에요. 이렇게 정의된 클래스·열거형 타입은 외부 링키지(external linkage)를 가져요(익명 네임스페이스에 있지 않다면).

이렇게 정의된 익명 클래스는 C 호환 구성 요소만 담아야 해요. 특히 다음이 금지돼요.
비정적 데이터 멤버, 멤버 열거형, 멤버 클래스 외의 멤버를 선언하기
기반 클래스나 기본 멤버 초기화기(default member initializer)를 갖기
람다 표현식을 포함하기
그리고 모든 멤버 클래스도 이 요구 사항을 (재귀적으로) 만족해야 해요

참고

| 타입 별명(type alias)은 typedef 선언과 같은 기능을 다른 문법으로 제공하며, 템플릿 이름에도 적용할 수 있어요. | (since C++11) |

키워드

typedef

예제

// simple typedef
typedef unsigned long ulong;

// the following two objects have the same type
unsigned long l1;
ulong l2;

// more complicated typedef
typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10];

// the following two objects have the same type
int a1[10];
arr_t a2;

// beware: the following two objects do not have the same type
const intp_t p1 = 0; // int *const p1 = 0
const int *p2;

// common C idiom to avoid having to write "struct S"
typedef struct { int a; int b; } S, *pS;

// the following two objects have the same type
pS ps1;
S* ps2;

// error: storage-class-specifier cannot appear in a typedef declaration
// typedef static unsigned int uint;

// typedef can be used anywhere in the decl-specifier-seq
long unsigned typedef int long ullong;
// more conventionally spelled "typedef unsigned long long int ullong;"

// std::add_const, like many other metafunctions, use member typedefs
template<class T>
struct add_const
{
    typedef const T type;
};

typedef struct Node
{
    struct listNode* next; // declares a new (incomplete) struct type named listNode
} listNode; // error: conflicts with the previously declared struct name

// C++20 error: "struct with typedef name for linkage" has member functions
typedef struct { void f() {} } C_Incompatible;

더 알아보기

  • 타입 별명(type alias)은 typedef와 같은 기능을 더 간결한 문법으로 제공하는데, 타입 별명 문법 문서에서 확인할 수 있어요.
  • cppreference의 typedef 원문에서 결함 보고(defect report) 기록을 더 볼 수 있어요.