让我们有一个值列表(foo.lst):
foo,
bar,
baz,
让我们把它转换为枚举。
enum foo {
#include "foo.lst"
_foo_length
};
让我们在 switch
中使用该枚举:
int main(void) {
enum foo[_foo_length];
switch(f[0]) {
case foo: return 0;
case bar: return 0;
case baz: return 0;
}
__builtin_unreachable();
}
(这段代码很蠢,但可以忽略)
问题:
使用-Wswitch
(包括在-Wall
中),GCC和Clang(可能还有其他编译器)会发出警告:
警告:枚举值'_foo_length'在switch语句中未被处理[-Wswitch]
解决方法:
- 禁用
-Wno-switch
可以隐藏该警告。
缺点:我们将失去有关switch缺少任何其他case
的警告。 - 添加一个
default: unreachable();
case。
缺点:我们将失去在编译时缺少case的警告,而选择在调试时遇到缺少的情况会导致运行时崩溃。 - 用
#define _foo_length (baz + 1)
替换枚举的最后一个值,使其不再是枚举的一部分。
缺点:需要手动更新该定义,每次向列表中添加值时都要这样做。某些人肯定会忘记,导致一切都出毛病。
理想情况下,应该有一种方法可以将枚举值标记为不可分配,从而使其在编译器读取可能的值时不产生警告,而不需要预处理器宏需要重复修改。
有类似的东西吗?还有其他我没有想到的选项吗?
switch
确实涵盖了所有情况? - Barmarcase _foo_length:
。 - Barmar-Wswitch
执行相反的测试。如果foo.lst
缺少其中一个名称,他将会得到未定义变量错误。但是我想知道为什么他会在switch
中硬编码名称,当他正在动态加载名称时,似乎存在设计错误。 - Barmar