typedef enum { A,B } type_t; int useType(type_t x) { switch (x) { case A: return 0; case B: return 1; } }
相关:Detecting if casting an int to an enum results into a non-enumerated value
解决方法
It is possible to define an enumeration that has values not defined by any of its enumerators.
现在,有一系列规则确切地指出哪些其他值可能用于其他类型的枚举.
有两类枚举.第一种是固定的基础类型,例如枚举type_t:int或enum类type_t.在这些情况下,基础类型的所有值都是有效的枚举器.
第二种不是固定的底层类型,其中包括诸如你的前C 11枚举.在这种情况下,可以通过以下方式总结关于值的规则:计算为了存储枚举的所有值所需的最小位数;那么在该位数中可表示的任何数字都是有效值.
因此 – 在您的特定情况下,单个位可以同时包含值A和B,因此3对于枚举器而言不是有效值.
但是如果你的枚举是A,B,C,那么即使没有具体列出3,它也是上述规则的有效值. (所以我们可以看到几乎所有的枚举都不是排他性的).
现在我们需要查看规则,了解如果有人确实尝试将3转换为type_t会发生什么.转换规则是C 14 [expr.static.cast] / 10,它表示生成了未指定的值.
但是,CWG issue 1766认识到C 14文本有缺陷,并将其替换为以下内容:
A value of integral or enumeration type can be explicitly converted to a complete enumeration type. The value is unchanged if the original value is within the range of the enumeration values (7.2). Otherwise,the behavior is undefined.
因此,在具有值0和1的两个枚举器的特定情况下,除非程序已经触发了未定义的行为,否则不可能有其他值,因此警告可能被视为误报.
要删除警告,请添加默认情况:执行某些操作的案例.为了防御性编程,我还建议,无论如何都有一个默认情况是个好主意.在实践中,它可能用于“包含”未定义的行为:如果有人确实传递了无效值,那么您可以干净地抛出或中止.
注意:关于警告本身:编译器不可能准确地警告控制流是否会到达函数的末尾,因为这需要解决停止问题.
他们倾向于谨慎行事:如果编译器不完全确定,则会发出警告,这意味着存在误报.
因此,此警告的存在并不一定表明可执行文件实际上允许进入默认路径.