Namespaces
Variants

Enumerations

From cppreference.net

열거형 은 명시적으로 명명된 상수( 열거자 )들의 값을 포함하는 기반 타입 (아래 참조)의 값을 가지는 별개의 타입 입니다.

목차

구문

열거형은 다음의 열거 지정자 선언 문법 에서 type-specifier 로 사용하여 선언됩니다:

enum attr-spec-seq  (선택 사항) identifier  (선택 사항) { enumerator-list } (1)
enum attr-spec-seq  (선택 사항) identifier  (선택 사항) : type { enumerator-list } (2) (C23부터)
1) 고정된 기본 타입 없이 열거형을 선언합니다.
2) 고정된 기반 타입 type 의 열거형을 선언합니다.

여기서 enumerator-list 는 쉼표로 구분된 목록 (후행 쉼표 허용) (C99부터) 으로, 각 항목은 다음과 같은 형태를 가집니다:

enumeration-constant attr-spec-seq  (optional) (1)
enumeration-constant attr-spec-seq  (optional) = constant-expression (2)

여기서

identifier , enumeration-constant - 이 선언으로 도입되는 식별자
constant-expression - 정수 상수 표현식 값이 int 타입의 값으로 표현 가능한 (C23 이전) . 열거형이 고정된 기반 타입을 가지는 경우, type 의 값으로 표현 가능한 (C23 이후)
attr-spec-seq - (C23) 선택적 속성 목록,
  • enum 뒤에 나타나면 전체 열거형에 적용됨
  • enumeration-constant 뒤에 나타나면 enumerator 에 적용됨

struct union 와 마찬가지로, 열거형 타입과 하나 이상의 열거형 상수를 도입하는 선언은 해당 타입이나 그로부터 파생된 타입의 객체 하나 이상을 선언할 수도 있습니다.

enum color { RED, GREEN, BLUE } c = RED, *cp = &c;
// enum color 타입을 도입합니다
// 정수 상수 RED, GREEN, BLUE
// enum color 타입의 객체 c
// enum color를 가리키는 포인터 타입의 객체 cp

설명

열거형 지정자 본문에 나타나는 각 enumeration-constant 는 포함하는 범위에서 정수 상수 (타입 int (C23 이전) )가 되며, 정수 상수가 필요한 모든 상황에서 사용할 수 있습니다 (예: case 레이블 또는 비 VLA 배열 크기로).

열거자 목록에서 각 열거 상수를 처리하는 동안, 열거 상수의 타입은 다음과 같아야 합니다:

  • 동일한 열거 상수의 재선언인 경우, 이전에 선언된 타입; 또는,
  • 고정된 기반 타입을 가진 열거형의 경우, 열거형 타입; 또는,
  • int , 열거자 목록에 이전 열거 상수가 없고 정의하는 정수 상수 표현식과 함께 명시적인 =가 없는 경우; 또는,
  • int , =와 함께 명시적으로 주어지고 정수 상수 표현식의 값이 int로 표현 가능한 경우; 또는,
  • =와 함께 명시적으로 주어지고 정수 상수 표현식의 값이 int 로 표현 불가능한 경우, 정수 상수 표현식의 타입; 또는,
  • 마지막 열거 상수의 값에 1을 더한 값의 타입. 이러한 정수 상수 표현식이 1의 덧셈으로 이전 열거 상수의 값에서 오버플로우 또는 래핑어라운드가 발생하는 경우, 타입은 다음 중 하나를 취합니다:
    • 이전 열거 상수 값에 1을 더한 값을 표현할 수 있는 적절한 크기의 부호 있는 정수 타입(비트 정밀 부호 있는 정수 타입 제외); 또는,
    • 이전 열거 상수 값에 1을 더한 값을 표현할 수 있는 적절한 크기의 부호 없는 정수 타입(비트 정밀 부호 없는 정수 타입 제외).

더해지는 이전 열거 상수가 부호 있는 정수 타입인 경우 부호 있는 정수 타입이 선택됩니다. 이전 열거 상수가 부호 없는 정수 타입인 경우 부호 없는 정수 타입이 선택됩니다. 새로운 값을 표현할 수 있는 앞서 설명된 적절한 크기의 정수 타입이 없는 경우, 열거형은 모든 값을 표현할 수 있는 타입을 가지지 않습니다.

(C23부터)
enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("red");
    break;
case GREEN:
    puts("green");
    break;
case BLUE:
    puts("blue");
    break;
}

만약 enumeration-constant 뒤에 = constant-expression 이 오는 경우, 그 값은 해당 상수 표현식의 값입니다. 만약 enumeration-constant 뒤에 = constant-expression 이 오지 않는 경우, 그 값은 동일한 열거형 내 이전 열거자의 값보다 1 큰 값입니다. 첫 번째 열거자의 값은 (만약 = constant-expression 을 사용하지 않는 경우) 0입니다.

enum Foo { A, B, C = 10, D, E = 1, F, G = F + C };
// A=0, B=1, C=10, D=11, E=1, F=2, G=12

식별자 자체가 사용되는 경우, 이는 태그 이름 공간 내에서 열거형 타입의 이름이 되며, enum 키워드 사용을 필요로 합니다(일반 이름 공간으로 typedef되지 않는 한).

enum color { RED, GREEN, BLUE };
enum color r = RED; // 정상
// color x = GREEN; // 오류: color는 일반 이름 공간에 없음
typedef enum color color_t;
color_t x = GREEN; // 정상

고정된 기반 타입이 없는 각 열거형 (고정된 기반 타입 없음) (C23부터) 은 다음 중 하나와 호환됩니다 : char , 부호 있는 정수 타입, 또는 부호 없는 정수 타입 ( bool 및 비트 정밀 정수 타입 제외) (C23부터) . 주어진 열거형과 호환되는 타입은 구현에 따라 정의되지만, 어떤 타입이든 해당 열거형의 모든 열거자 값을 표현할 수 있어야 합니다. 고정된 기반 타입이 있는 모든 열거형에 대해, 열거형 타입은 열거형의 기반 타입과 호환됩니다. (C23부터)

고정된 기반 타입이 없는 열거형의 완료 시점에서 열거 멤버 타입은:

  • int 만약 열거형의 모든 값이 int 로 표현 가능한 경우; 또는,
  • 열거형 타입 자체입니다.
(C23부터)
모든 열거형은 기반 타입을 가집니다. 기반 타입은 enum-type-specifier를 사용하여 명시적으로 지정될 수 있으며, 이는 고정된 기반 타입입니다. 명시적으로 지정되지 않은 경우, 기반 타입은 열거형의 호환 타입으로, 부호 있는 정수 타입, 부호 없는 정수 타입, 또는 char 입니다. (C23부터)

열거형은 정수형이며, 따라서 다른 정수형을 사용할 수 있는 모든 곳에서 사용될 수 있습니다. 여기에는 암시적 변환 산술 연산자 가 포함됩니다.

enum { ONE = 1, TWO } e;
long n = ONE; // 승격
double d = ONE; // 변환
e = 1.2; // 변환, e는 이제 ONE
e = e + 1; // e는 이제 TWO

참고 사항

C에서는 struct union 와 달리, 전방 선언된 enum이 존재하지 않습니다:

enum Color; // 오류: C에서 enum에 대한 전방 선언은 불가능합니다
enum Color { RED, GREEN, BLUE };

열거형은 #define 보다 더 편리하고 구조화된 방식으로 명명된 상수를 선언할 수 있게 합니다. 디버거에서 가시적이며, 범위 규칙을 따르고, 타입 시스템에 참여합니다.

#define TEN 10
struct S { int x : TEN; }; // 정상

또는

enum { TEN = 10 };
struct S { int x : TEN; }; // 역시 OK

C23 이후로 constexpr 을 동일한 목적으로 사용할 수 있습니다:

constexpr int TEN = 10;
struct S { int x : TEN; }; // 역시 OK

게다가, struct union 이 C에서 자신의 스코프를 설정하지 않기 때문에, 열거형 타입과 그 열거 상수들은 전자의 멤버 명세에서 도입될 수 있으며, 그들의 스코프는 이후 전자의 스코프와 동일합니다.

struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
// enum State 타입과 그 열거형 상수들은 여기서도 계속 보입니다, 예를 들어
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // 1 2 3을 출력합니다
}

예제

#include <stdio.h>
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}

출력:

List of cable stations:
 FOX:   11
 HBO:   22
 MAX:   30

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.2.5/21 유형 (p: 39)
  • 6.7.2.2 열거형 지정자 (p: 107-112)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.2.5/16 Types (p: 32)
  • 6.7.2.2 Enumeration specifiers (p: 84-85)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.2.5/16 유형 (p: 41)
  • 6.7.2.2 열거형 지정자 (p: 117-118)
  • C99 표준 (ISO/IEC 9899:1999):
  • 6.2.5/16 Types (p: 35)
  • 6.7.2.2 Enumeration specifiers (p: 105-106)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 3.1.2.5 유형
  • 3.5.2.2 열거자 지정자

키워드

enum

참고 항목

C++ 문서 for enumeration declaration