是否有一种编译时方法来检测/防止 C/C++ 枚举中的重复值?
问题是有多个项目被初始化为显式值。
背景:
我继承了一些 C 代码,如下所示:
#define BASE1_VAL (5)
#define BASE2_VAL (7)
typedef enum
{
MsgFoo1A = BASE1_VAL, // 5
MsgFoo1B, // 6
MsgFoo1C, // 7
MsgFoo1D, // 8
MsgFoo1E, // 9
MsgFoo2A = BASE2_VAL, // Uh oh! 7 again...
MsgFoo2B // Uh oh! 8 again...
} FOO;
问题在于,随着代码的增长和开发人员向 MsgFoo1x
组添加更多消息,最终它会超出 BASE2_VAL
。
此代码最终将迁移到 C++,因此如果有一个仅 C++ 的解决方案(模板魔术?),那没关系 - 但与 C 和 C++ 一起使用的解决方案更好。
最佳答案
有几种方法可以检查此编译时间,但它们可能并不总是适合您。首先在 MsgFoo2A 之前插入一个“标记”枚举值。
typedef enum
{
MsgFoo1A = BASE1_VAL,
MsgFoo1B,
MsgFoo1C,
MsgFoo1D,
MsgFoo1E,
MARKER_1_DONT_USE, /* Don't use this value, but leave it here. */
MsgFoo2A = BASE2_VAL,
MsgFoo2B
} FOO;
现在我们需要一种方法来确保 MARKER_1_DONT_USE < BASE2_VAL
在编译时。有两种常见的技术。
负大小数组
声明一个负大小的数组是错误的。这看起来有点难看,但确实有效。
extern int IGNORE_ENUM_CHECK[MARKER_1_DONT_USE > BASE2_VAL ? -1 : 1];
如果 MARKER_1_DONT_USE 大于 BASE_2_VAL,几乎所有编写过的编译器都会产生错误。 GCC 吐槽:
test.c:16: error: size of array ‘IGNORE_ENUM_CHECK’ is negative
静态断言
如果您的编译器支持 C11,您可以使用 _Static_assert
.对 C11 的支持并不普遍,但您的编译器可能支持 _Static_assert
无论如何,特别是因为 C++ 中的相应功能得到了广泛的支持。
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
GCC 吐出以下信息:
test.c:16:1: error: static assertion failed: "Enum values overlap."
_Static_assert(MARKER_1_DONT_USE < BASE2_VAL, "Enum values overlap.");
^
关于c++ - 检测多个枚举项何时映射到相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2576868/