如何在C中模拟强类型枚举?

BЈо*_*вић 16 c enums

在C++ 03中,可以通过将其置于类(或命名空间)中来模拟强类型枚举:

struct MyEnum
{
  enum enumName
  {
    VALUE_1 = 1,
    VALUE_2,
  };
};
Run Code Online (Sandbox Code Playgroud)

并使用它:

MyEnum::enumName v = MyEnum::VALUE_1;
Run Code Online (Sandbox Code Playgroud)

是否有可能在C中做类似的事情?如果有,怎么样?


我试过这样,但当然不起作用:

struct A
{
  enum aa
  {
    V1 = 5
  };
};

int main()
{
  A::aa a1 = A::V1;
  enum A::aa a2 = A::V1;
  struct A::aa a3 = A::V1;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ric*_*III 6

这是我的解决方案.与@ Eric的设计相比有一些优势:

  • 支持相等测试(例如A_VALUE_0 == value)
  • 不依赖于C99的复合文字
  • 可以强制转换为枚举赋值不正确.

缺点:

  • 标志不起作用(例如A_VALUE_0 | A_VALUE_1)
  • 不能switch'd
  • 在测试相等性时,可以将IDE混淆错误行的位置(例如A_VALUE_0 == B_VALUE_1)

笔记:

  • 永远不要取消引用此类型的指针.会导致崩溃比兰博基尼更快

这是实现(用-Werror&编译-pedantic):

typedef struct A { char empty[1]; } *A; // we use 'empty' so that we don't get a warning that empty structs are a GNU extension
#define A_VALUE_0 ((A) 0x1)
#define A_VALUE_1 ((A) 0x2)
#define A_VALUE_2 ((A) 0x4)

typedef struct B { char empty[1]; } *B;

#define B_VALUE_0 ((B) 0x0)
#define B_VALUE_1 ((B) 0x1)
#define B_VALUE_2 ((B) 0x2)

int main()
{
    A a = A_VALUE_0;

    int equal = (a == A_VALUE_1); // works!
    int euqal = (a == B_VALUE_1) // doesn't work

    A flags = A_VALUE_0 | A_VALUE_1; // doesn't work!

    switch (a) { // doesn't work
        case A_VALUE_0:
            puts("value 0");
            break;
        case A_VALUE_1:
            puts("value 1");
            break;
        case A_VALUE_2:
            puts("value 2");
            break;
        default:
            puts("unknown value");
            break;
    } // doesn't work

    // casting works for assignment:
    A b = (A) (B_VALUE_2);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*hil 3

你可以这样做:

// Declare A to use for an enumeration, and declare some values for it.
typedef struct { int i; } A;
#define A0  ((A) { 0 })
#define A1  ((A) { 1 })

// Declare B to use for an enumeration, and declare some values for it.
typedef struct { int i; } B;
#define B0  ((B) { 0 })
#define B1  ((B) { 1 })


void foo(void)
{
    // Initialize A.
    A a = A0;

    // Assign to A.
    a = A1;

    // Assign a value from B to A.
    a = B0; // Gets an error.
}
Run Code Online (Sandbox Code Playgroud)

这为您提供了一些输入,但这可能会很麻烦,具体取决于您想要对枚举及其值执行哪些其他操作。

  • 这里的大问题是相等性测试不起作用,即 `A a = A0 ; A b = A0 ; bool foo = (a == b);` 无法编译。另外,不能在开关中使用 A 类型的变量。 (8认同)