我有一个烦人的错误,我忘记写do一个do ... while循环。
int main() {
int status=1;
/*do*/ {
status = foo();
} while (status);
}
Run Code Online (Sandbox Code Playgroud)
为什么这仍然编译和运行?在我看来,编译器应该拒绝这是荒谬的或至少发出警告(-Wall我的编译器选项中有)。我正在使用 C++11。
据我所知,大括号代码运行{ ... },然后程序检查 while 子句中的条件。
Che*_*yDT 92
我假设你实际上有int status 外循环体,否则代码不会编译。(甚至没有用的do到位。)
修复后,您编写的代码在没有 的情况下仍然有效do,但正如您已经正确指出的那样,做了一些不同的事情。让我稍微改写一下,以显示它是如何解释的:
int main () {
int status;
{ // anonymous braced block that just creates a new scope
status = foo();
}
while (status) {
// empty loop body
}
}
Run Code Online (Sandbox Code Playgroud)
像这样的独立块确实有其用途,例如利用RAII - 它可以包含一个带有对象的局部变量,该对象的析构函数在超出范围时释放一些资源(例如文件句柄)等。
之所以与while (status);the 相同,while (status) {}是因为您可以放置单个语句或块,并且;是一个不执行任何操作的有效语句。
并且编写类似的东西while (someVariable);一般来说甚至不是荒谬的(尽管在这种情况下当然是这样)因为它本质上是一个自旋锁,一种忙等待的形式 - 如果另一个处理器内核,某些 I/O 组件或中断会修改 的值,someVariable从而不再满足条件,并且不会有任何延迟。您可能不会在“占用 CPU”是一件坏事的桌面平台上编写这样的代码(内核模式代码中的特定场景除外),而是在像微控制器这样的嵌入式设备上(您的代码是唯一运行的代码) ) 它可以是实现等待某些外部更改的代码的完全有效的方式。正如 Acorn 在评论中指出的那样,这当然只有在以下情况下才有意义someVariable是volatile (或以其他方式不可预测),但我通常谈论的是变量上的繁忙循环。
Mar*_*tin 14
编译器不能在此处引发错误,因为根据 C++11 标准的第 6.5 节,这是完全有效的代码。实际上有两种口味while:
while ( condition ) statementdo statement while ( expression );statement 可
;)考虑到这一点,让我格式化您的代码,编译器如何看待它:
int main () {
int status;
{ // braced block that just creates a new scope
status = foo();
}
while (status) /* empty statement */;
}
Run Code Online (Sandbox Code Playgroud)
虽然对于人类读者来说很明显您打算循环花括号中的代码,但这对编译器来说并不明显。这与 C++ 编译器通常不考虑缩进和换行符的事实有关。将它们考虑在内的分析工具可能会警告您,您格式化代码的方式与它实际执行的操作不一致,并为您纠正。这会让你的错误更明显。或者也许有一天我们会得到一种语言特性,它允许我们明确地说“空语句”。这将使我们能够清楚地说明我们的意图。一旦我们知道编译器可能会在代码不清楚时发出警告。在那之前我们必须小心——C++ 是一种强大的语言,但它有一些锋利的边缘......
顺便说一句,您不是第一个从缩进/换行中得出错误结论的人。
为什么这仍然编译和运行?
不是因为status没有定义。
在我看来,编译器应该拒绝这是荒谬的或至少发出警告(我的编译器选项中有 -Wall )。
假设您定义了status,它是一个有效的程序。一些编译器或分析器可能会为无限循环或无操作while体生成警告。