当我使用带有“警告级别4”的Visual C ++ 9编译C ++代码时:
while( true ) {
//loop body with break on certain condition
}
以及以下内容:
for( ; true; ) {
//same loop body
}
都会触发C4127: conditional expression is constant
警告但以下内容:
for( ; ; ) {
//same loop body
}
在没有警告的情况下编译。
为什么会出现这种差异,特别是在第二种和第三种变体之间?
答案 0 :(得分:10)
警告用户持续条件表达式的原因是为了帮助避免表达式最终为常量的错误(例如,由于拼写错误)。在最后一种情况下,没有表达式,因此不存在意外不变的风险。
答案 1 :(得分:7)
原因很简单,虽然很愚蠢。
诊断无限循环很重要,但这可能不明显:
while(i >= 0) { --i; } // infinite if i unsigned
while(SOME_MACRO(i)) // err, depends on the expansion of macros
编译器的一个很棒的功能是为重复测试产生警告,这是一个结果总是为真或总是为假的测试,因为它来自宏扩展或在依赖的背景。
似乎VC ++在这里推得太过分了,而不是考虑同义条件警告它可以找到的所有true
或false
条件,即使它们已在代码中明确说明
答案 2 :(得分:4)
for ( ;; )
构造是故意编码“无限”循环的规范方式。我可以想象编译器设计者不想为此生成警告。
答案 3 :(得分:4)
没有意义。毕竟,langauge规范说($ 6.5.3 / 2),
其中一个或两个条件和 表达式可以省略。 :一种 缺失条件使隐含 while子句相当于 而(真)。强>
即使根据标准,for ( ; ; )
也相当于while(true)
。因此,我没有看到任何理由为什么编译器应该在一个案例中发出警告而不在另一个案例中发出警告!
-
如果编译器决定发出警告,那么在我看来,编译器应该在条件缺失而不是存在时发出警告,以便警告被解释为提示让程序员明确提及意图并明确 。
我的意思是,for ( ;; )
更可能是一个错字,而不是显式提到for ( ;true; )
中的条件。后者告诉程序员清晰明确的意图。正如 Steve 在评论中所说:
对于int值y,char x = y是 相当于char x =(char)y,但是 你可能想要一个警告 隐含的缩小转换 第一个但不是第二个。
所以明确的意图不应该收到警告,而隐含的意图应该收到!
答案 4 :(得分:1)
编译器警告可以帮助捕获潜在的错误。在true
循环中使用始终while
条件可能是一个错误。例如,在下面的代码中,这可能是一个错误,我希望编译器警告我:
unsigned int x;
// ...
while (x >= 0) {
// ...
}
在这种情况下,在优化构建中,编译器可能会推断条件始终为真(因为无符号整数不能小于0)。因此,需要在true
循环中检测始终while
条件。我认为,无论谁编写了这种错误的检测都没有特殊情况while (true)
的情况,因为有一种简单的方法可以使用for (;;)
进行无限循环。
您可以阅读here,如何决定是否在Visual Studio中添加警告(例如C#
,但我认为团队有相同的经验法则警告C++
)。