Bar*_*rry 53 c++ compiler-warnings switch-statement
switch
语句可能非常有用,但会导致程序员忘记break语句的常见错误:
switch(val) {
case 0:
foo();
break;
case 1:
bar();
// oops
case 2:
baz();
break;
default:
roomba();
}
Run Code Online (Sandbox Code Playgroud)
你不会明显得到警告,因为有时明确需要通过.良好的编码风格建议在你的堕落是故意的时候发表评论,但有时这是不够的.
我很确定这个问题的答案是否定的,但是:如果你case
不这样做,那么当前(或将来会提出)是否能够让编译器抛出错误(或者至少是警告!)至少有一种break;
或某种效果// fallthru
?使用switch
语句有一个防御性编程选项会很好.
Sha*_*our 67
好铿锵有-Wimplicit-fallthrough
哪些我不知道但通过使用找到-Weverything
.所以对于这段代码,它给了我以下警告(现场直播):
warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
case 2:
^
note: insert '[[clang::fallthrough]];' to silence this warning
case 2:
^
[[clang::fallthrough]];
note: insert 'break;' to avoid fall-through
case 2:
^
break;
Run Code Online (Sandbox Code Playgroud)
我可以在此标志中找到的唯一文档位于" 属性参考"中,其中说明:
clang :: fallthrough属性与-Wimplicit-fallthrough参数一起使用,用于注释switch标签之间的故意直通.它只能应用于放置在任何语句和下一个开关标签之间的执行点的空语句.通常使用特定注释标记这些位置,但此属性旨在用更严格的注释替换注释,编译器可以检查注释.
并提供了如何标记显式掉落的示例:
case 44: // warning: unannotated fall-through
g();
[[clang::fallthrough]];
case 55: // no warning
Run Code Online (Sandbox Code Playgroud)
这种使用属性来标记显式的直通性具有不可移植的缺点.Visual Studio
生成错误并gcc
生成以下警告:
warning: attributes at the beginning of statement are ignored [-Wattributes]
Run Code Online (Sandbox Code Playgroud)
如果你想使用这是一个问题-Werror
.
我试过这个,gcc 4.9
看起来gcc
不支持这个警告:
错误:无法识别的命令行选项'-Wimplicit-fallthrough'
从GCC 7开始,-Wimplicit-fallthrough
支持__attribute__((fallthrough))
并可用于在有意进行跌穿时抑制警告.GCC确实在某些情况下识别出"通过"评论,但它可以很容易地混淆.
我没有看到产生这种警告的方法Visual Studio
.
请注意,Chandler Carruth解释说这-Weverything
不适合生产用途:
这是一个疯狂的团体,从字面上实现了Clang的每一个警告.不要在代码中使用它.它仅供Clang开发人员使用,或用于探索存在的警告.
但它有助于弄清楚存在什么警告.
在C++ 17中,我们得到[dcl.attr.fallthrough] p1中涵盖的属性[[fallthough]]:
属性标记可以应用于null语句(9.2); 这样的陈述是一个突破性的陈述.属性 - 标记通过在每个属性列表中最多出现一次,并且不存在attributeargument-子句.fallthrough语句只能出现在封闭的switch语句中(9.4.2).在fallthrough语句之后执行的下一个语句应该是带标签的语句,其标签是同一switch语句的case标签或default标签.如果没有这样的声明,该计划就是不正确的.
...
Run Code Online (Sandbox Code Playgroud)[ Example: void f(int n) { void g(), h(), i(); switch (n) { case 1: case 2: g(); [[fallthrough]]; case 3: // warning on fallthrough discouraged h(); case 4: // implementation may warn on fallthrough i(); [[fallthrough]]; // ill-formed } } —end example ]
Aar*_*aid 12
我总是写break;
每之前case
,如下所示:
switch(val) {
break; case 0:
foo();
break; case 1:
bar();
break; case 2:
baz();
break; default:
roomba();
}
Run Code Online (Sandbox Code Playgroud)
这样,如果break;
缺少一个,那么对眼睛来说就更加明显了.break;
我认为最初是多余的,但它有助于保持一致.
这是一个传统的switch
陈述,我只是以不同的方式使用空格,删除通常在a之后break;
和之前的新行case
.
建议:如果你一直在case子句之间加上一个空行,那么人们在查看代码时就会看到没有'break'变得更加明显:
switch (val) {
case 0:
foo();
break;
case 1:
bar();
case 2:
baz();
break;
default:
roomba();
}
Run Code Online (Sandbox Code Playgroud)
当个别case子句中有很多代码时,这并不是那么有效,但这本身往往是一个糟糕的代码味道.