c – “控制到达非空函数的结束”,在枚举类型上使用完全处理的情况切换

前端之家收集整理的这篇文章主要介绍了c – “控制到达非空函数的结束”,在枚举类型上使用完全处理的情况切换前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
为什么即使处理了type_t的所有可能值,此代码也会触发“控制到达非void函数的结尾”?处理此警告的最佳方法是什么?切换后添加返回-1?(代码测试 here)
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

解决方法

一般来说,枚举不是唯一的.有人可以像useType((type_t)3)一样调用你的函数;例如.这在C 14 [dcl.enum] / 8中具体提到:

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的两个枚举器的特定情况下,除非程序已经触发了未定义的行为,否则不可能有其他值,因此警告可能被视为误报.

删除警告,请添加默认情况:执行某些操作的案例.为了防御性编程,我还建议,无论如何都有一个默认情况是个好主意.在实践中,它可能用于“包含”未定义的行为:如果有人确实传递了无效值,那么您可以干净地抛出或中止.

注意:关于警告本身:编译器不可能准确地警告控制流是否会到达函数的末尾,因为这需要解决停止问题.

他们倾向于谨慎行事:如果编译器不完全确定,则会发出警告,这意味着存在误报.

因此,此警告的存在并不一定表明可执行文件实际上允许进入默认路径.

猜你在找的C&C++相关文章