如何在C中模拟强类型枚举?
在C++03中,可以通过将其放在类(或命名空间)中进行模拟: 使用它:如何在C中模拟强类型枚举?,c,enums,C,Enums,在C++03中,可以通过将其放在类(或命名空间)中进行模拟: 使用它: MyEnum::enumName v = MyEnum::VALUE_1; 有可能在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; retur
MyEnum::enumName v = MyEnum::VALUE_1;
有可能在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;
}
您可以这样做:
// 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.
}
这会给您一些键入操作,但这可能会造成麻烦,具体取决于您希望对枚举及其值执行的其他操作。这是我的解决方案。与@Eric的设计相比有一些优势:
- 支持相等性测试(例如
)A_值\u 0==VALUE
- 不依赖C99的复合文本
- 可以强制转换为枚举分配不正确的值李>
- 标志不起作用(例如
)A_值0 | A_值1
- 不能是
'd开关
- 在测试相等性时,可能会混淆IDE错误行的位置(例如,
)A_值_0==B_值_1
- 切勿取消引用此类型的指针。会导致比兰博基尼更快的车祸
-Werror
和-pedantic
编译):
由于C不提供名称空间,因此可以使用前缀
enum MyEnum {
MyEnumA = 1,
MyEnumB,
MyEnumC
};
enum OtherEnum {
OtherEnumA = 1,
OtherEnumB
};
然后,为了变量声明的简洁性,可以为枚举声明类型,如下所示:
typedef enum MyEnum MyEnum;
typedef enum OtherEnum OtherEnum;
最后,如果您不想允许将OtherEnumB
隐式转换为MyEnum
类型,那么Clang提供了-Wenum转换
标志(不幸的是,我认为GCC中没有类似的标志)
它的优点是简单、易于理解,并且可以很好地与您(至少是我的)IDE的自动完成功能配合使用。C中没有名称空间和类,因此您不能。.在C99中,可能需要通过用下划线替换范围运算符来处理可变宏。但是在普通的C89中,我认为这是不可能的。@ AJG85:C中的结构与C++中的结构不一样,C++中它们是类,而在C中它们不是。fine@tuxtimo:实际上,C为标识符提供了四种不同的名称空间。一个用于标签,一个用于结构、联合和枚举标记,一个用于结构和联合成员,最后一个用于所有其他标识符,包括枚举常量。赋值使用C99功能(),但其余也适用于C89。@Shahbaz这对我来说适用于
gcc-ansi
(使用gcc 4.1.2)。@rwos,啊,是的。我现在记得我不能写它(在我的一些代码中),因为我是用g++编译的,而不是说它是C11。我的错。这里的大问题是平等性测试不起作用,即A=A0;A b=A0;bool-foo=(a==b)代码>不编译。此外,您不能在开关中使用类型A的变量。@EricFinn gcc with-ansi-pedantic
显示警告(“ISO C90禁止复合文字”)。另一方面:谁只使用C89/90编译了?:-)+1,一些注释:我仍然会使用底部的enum
来声明值。如果添加了值,则更易于维护,例如,为了避免某些旧编译器出现令人毛骨悚然的整数到指针警告,您应该查看uintpttr\u t
,类似于((B)(uintptpr\u t)0x2)
。要声明指向struct
的指针,甚至不必声明结构本身,typedef struct spooky\u struct*a
就足够了。这种方法依赖于协作实现定义的行为“整数可以转换为任何指针类型…”。。。,结果是实现已定义,可能未正确对齐,可能未指向引用类型的实体,并且可能是陷阱表示。“C17dr§6.3.2.3 5边缘编码。我知道这是3年后的事了,所以如果没有回复,不用担心。您使用的是g++吗?有了gcc,我就无法实现这一点。我尝试了4.6和4.7版本,还添加了-Wextra,-Wall-Wenum compare。我使用了叮当。我假设GCC也会为enum
类型之间的隐式转换发出警告,但我可能错了。看起来GCC只在使用-Wenum compare
时发出比较警告。啊,对了。它的工作原理和你描述的一样。我也尝试了最近的gcc,但仍然没有警告。也有bug报告和讨论,但gcc开发人员似乎对现状感到满意,因为“标准说所有这些都是有效的”。
enum MyEnum {
MyEnumA = 1,
MyEnumB,
MyEnumC
};
enum OtherEnum {
OtherEnumA = 1,
OtherEnumB
};
typedef enum MyEnum MyEnum;
typedef enum OtherEnum OtherEnum;
/tmp/test.c:24:20: warning: implicit conversion from enumeration type 'enum OtherEnum' to different enumeration type 'MyEnum' (aka 'enum MyEnum') [-Wenum-conversion]
MyEnum value = OtherEnumB;
~~~~~ ^~~~~~~~~~
1 warning generated.