C 为什么开关(0)不产生警告,而如果(0)产生警告?
鉴于此代码:C 为什么开关(0)不产生警告,而如果(0)产生警告?,c,visual-studio-2012,gcc,clang,C,Visual Studio 2012,Gcc,Clang,鉴于此代码: #include <stdio.h> int main( int argc, char** argv ) { switch (0) { case 1: printf("1"); case 2: printf("2"); default: printf("default"); break; } return 0; } #包括 int main
#include <stdio.h>
int main( int argc, char** argv )
{
switch (0) {
case 1: printf("1");
case 2: printf("2");
default:
printf("default");
break;
}
return 0;
}
#包括
int main(int argc,字符**argv)
{
开关(0){
案例1:printf(“1”);
案例2:printf(“2”);
违约:
printf(“违约”);
打破
}
返回0;
}
我希望编译器会告诉我关于条件表达式是常量(switch(0)
,而VS2012会针对if(0)
)或无法访问的代码(case1
,case2
)发出此警告
然而,无论是在Visual Studio 2012上,还是在最近的GCC上,我都没有收到类似的消息
为什么连体面的编译器都不抱怨呢?我刚试过
clang-Weverything
:它抱怨没有使用argc
和argv
,但对开关(0)
保持沉默,就像gcc
一样
虽然编译器不必发出诊断,但如果错误是打字错误,则警告可能会有所帮助。试试这个例子:
int test(int l) {
switch (1) {
case 0: return 0;
case 1: return 1;
default: return -1;
}
您应该在两个项目上都提交一个bug
编辑:
clang
最近似乎已经解决了这个问题,与Ryker在回复中所显示的不同,-Wunreachable code
不会在我的笔记本电脑上抱怨。我可能有一个较旧的版本。我只是在打开“扩展警告”的情况下在CLANG上尝试了它,并收到以下警告:
奇怪的是,仅指交换机中两行中永远不会执行的第一行:
case 1: printf("1");
要在Visual Studio 2013中获取警告,您需要:
1一致性实施应产生至少一条诊断信息(在 一种实现定义的方式)如果是预处理翻译单元或翻译单元 包含违反任何语法规则或约束的行为,即使该行为也是显式的 指定为未定义或实现已定义诊断消息不需要显示 在其他情况下产生。9)
9) 其目的是一个实现应该识别每一个的性质,并在可能的情况下进行本地化 违反当然,一个实现可以自由地生成任意数量的诊断,只要 有效的程序仍被正确翻译。它还可以成功地翻译无效的程序。 重点补充 因此,如果在
开关中使用常量表达式,或者如果控制表达式违反约束,则需要进行诊断
6.8.4.1if
语句
约束
1if
语句的控制表达式应具有标量类型。
…
6.8.4.2开关
语句
约束
1开关的控制表达式应为整数类型。
2如果开关
语句在
带有可变修改类型的标识符,整个开关
语句应在
该标识符的范围。154)
3每个案例
标签的表达式应为整数常量表达式,且不得有两个
同一开关语句中的case常量表达式应具有相同的值
转换后。switch语句中最多可以有一个default
标签。
(任何封闭的开关
语句都可能有默认值
标签或大小写
常量
表达式的值与封闭表达式中的大小写
常量表达式重复
开关
语句。)
154)也就是说,声明要么在开关
语句之前,要么在最后一个大小写
之后,或者
default
标签与包含声明的块中的开关关联。
…事实并非如此
这基本上是一个执行质量问题;实现可能会发出一个诊断,用于在if
或switch
语句中使用常量表达式,但不必这样做<代码>如果(0)
和开关(0)
可能会让我们大多数人觉得不可靠,但实现不需要对它们发出任何诊断 你会期望这样的警告在实际代码中捕捉到很多bug吗?@KerrekSB:好吧,因为if(0)代码>会导致一个警告(在VisualStudio中条件表达式是常量),我想这里应该是这样的,我想区别在于警告可能有用的频率。恒定if
条件是很常见的;使用常量<代码>开关<代码>值的情况要少得多,几乎是“我不记得在野外见过一个”。但是,我可以看到它在某些上下文中可能很有用-switch(sizeof(somevar))
后跟处理不同机器类型的代码(例如case2:…;break;case4:…;break;case8:…;break;default:assert(0);break;
)。我不确定这是否好,但它可能是有效的。@chqrlie我试过gcc-Werror
。没有警告/errors@ManosNikolaidis-Werror
是一个骗局,它不会激活任何额外的警告,它只会使所有警告行为像错误一样。发生这种情况的原因很清楚:case
标签只是标签,开关中的整个块永远不会被执行,因此clang
只会对块发出警告,不是每句话都是如此。@xxl-当然。这是有道理的,只是执行了default
case语句。这个答案说明了明显的-没有用。@anatolyg:which