Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是GCC';s-Wmaybe未初始化为基于枚举的switch语句生成带有-O1的虚假警告?_C_Gcc_Enums_Compiler Warnings_Gcc6 - Fatal编程技术网

是GCC';s-Wmaybe未初始化为基于枚举的switch语句生成带有-O1的虚假警告?

是GCC';s-Wmaybe未初始化为基于枚举的switch语句生成带有-O1的虚假警告?,c,gcc,enums,compiler-warnings,gcc6,C,Gcc,Enums,Compiler Warnings,Gcc6,我有一段代码,格式如下: typedef enum {A=1,B} EnumType; int foo (EnumType x) { int r; switch (x) { case A: r = 1; break; case B: r = 2; break; /* default: r = -1; break; */ } return r; } 我使用GC

我有一段代码,格式如下:

typedef enum {A=1,B} EnumType;

int foo (EnumType x)
{
  int r;
  switch (x) {
    case A:
      r = 1;
      break;
    case B:
      r = 2;
      break;
      /*
    default:
      r = -1;
      break;
      */
  }
  return r;
}
我使用GCC 6.3.0进行编译并收到警告:

$ gcc --version
gcc (MacPorts gcc6 6.3.0_2) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc -c -Wall -O1 test.c
test.c: In function 'foo':
test.c:20:10: warning: 'r' may be used uninitialized in this function [-Wmaybe-uninitialized]
   return r;
          ^
代码对我来说似乎是安全的,而且确实有一些关于它的讨论

这是虚假警告吗?

更多相关信息:

  • 添加注释掉的
    默认值:
    块可解决警告问题
  • 警告不会随
    -O0

此警告完全正确,因为
枚举
类型不会将可能的值限制在此
枚举
中定义的成员--它可以保留基础整数类型的任何值。因此,如果交换机中没有
default
分支,您确实可以使用未初始化的
r
来显示代码


我可以用
gcc
-O0
用问题中显示的确切代码重现缺少的警告,因此在我看来这就像
gcc
中的一个bug。不管优化级别如何,都应该给出警告。

很容易弄清楚:存在可能的程序路径,其中r将在未初始化的情况下返回。所以你得到了警告。Enum只是int,所以有很多可能的情况

在运行时,不会根据这些值检查枚举

关于问题的第二部分。这是有意的,因为任何级别的优化都可能(在这种情况下,如果枚举类型的值是非法的,则将删除代码-编译器假定不可能有其他值)

这个案例非常有趣:

您可能认为您已经检查了非法值。但是编译器已经删除了代码:)


顺便说一句-有趣的是,为什么我的答案被否决了

为什么这个警告不会与
-O0
一起出现?这可能是一个bug。“无效”
enum
值是可能的,无论优化级别如何。@Felix Palmen这不是一个bug。这是有意的-打开优化后,可以优化某些语句。这场讨论发生在10-12年前的gnu讨论名单上。在我的回答中,关于如何处理这一问题进行了长时间的讨论。甚至无法检查x是否有有效值,因为编译器知道如果没有,它就是UB。因此发出了警告——在这种情况下,这一条无关紧要。代码有可能是UB,警告应该是警告这一点,而不发出
-O0
的警告是一个bug。我对它投了反对票,因为在编辑之后它现在完全错了。优化与所讨论的代码显示出可能的UB这一事实无关。别胡说八道了,我很乐意收回我的投票。不,我否决了错误的答案。警告不应依赖于优化。对于
gcc
,其中一些很不幸会这样做,但在这种情况下,它们需要优化器以获得更好的精度
-Wmaybe uninitialized
不是其中之一,因为它的定义很容易在源代码中发现。您在这里走错了。@FelixPalmen,恐怕任何实现都可以警告用户,而不会以任何方式显示UB。警告依赖于实现,当实现决定不发出警告时,标准遵从性不会受到影响。PeterJ的解释是完全正确的,恐怕与gcc的实现是一致的。在这种情况下,由于编译后的程序中可能存在UB,我们处于编译错误程序的情况下,编译器可以自由发出警告,并编译为最终工作程序。当然,关于这一点的警告是完全可选的,许多编译器都不提供警告。要点是:
gcc
确实提供了一个,并且根据
gcc
文档,它不依赖于优化级别。因此,如果
gcc
-O0
中缺少此警告,则这是一个
gcc
错误(或至少是一个错误的文档)。@Felix Palmen-报告它。并让我们知道答案是。如果您100%地知道x将永远不会有一个您没有提供案例的值,您可以添加
默认值:u builtin_uunreachable()作为编译器的提示。有关更多信息,请参阅。