C++ 忘了做在做。。。while循环
我有一个恼人的bug,我忘了在C++ 忘了做在做。。。while循环,c++,C++,我有一个恼人的bug,我忘了在do中写do。。。而循环 int main() { int status=1; /*do*/ { status = foo(); } while (status); } 为什么它仍然编译并运行?在我看来,编译器应该以无意义为由拒绝这一点,或者至少发出警告(我的编译器选项中有-Wall)。我正在使用C++11 据我所知,带括号的代码运行{…},然后程序无限检查while子句中的条件。我假设您实际上在循环体之外有int status,否则代码将无法
do中写do
。。。而
循环
int main() {
int status=1;
/*do*/ {
status = foo();
} while (status);
}
为什么它仍然编译并运行?在我看来,编译器应该以无意义为由拒绝这一点,或者至少发出警告(我的编译器选项中有-Wall
)。我正在使用C++11
据我所知,带括号的代码运行{…}
,然后程序无限检查while子句中的条件。我假设您实际上在循环体之外有int status
,否则代码将无法编译。(即使在do
到位的情况下也不行。)
有了这个修正,您编写的代码在没有do
的情况下仍然有效,但是做了一些不同的事情,正如您已经正确指出的那样。让我稍微重写一下,看看它是如何解释的:
int main(){
智力状态;
{//刚刚创建新作用域的匿名大括号块
状态=foo();
}
while(状态){
//空环体
}
}
像这样的独立块,例如利用-它可以包含一个局部变量和一个对象,该对象的析构函数在超出范围时释放一些资源(例如文件句柄),等等
while(状态)的原因
与相同,而(status){}
是因为允许您放置单个语句或块,并且
是一个无效的语句
写一些东西,比如
while(someVariable)代码>一般来说甚至不是毫无意义的(虽然在本例中它当然是),因为它本质上是一个自旋锁,一种繁忙等待的形式-如果另一个处理器内核、某些I/O组件或中断修改someVariable
的值,从而不再满足条件,它将离开循环,它将毫不拖延地这样做。您可能不会在桌面平台上编写这样的代码,因为“占用CPU”是一件坏事(内核模式代码中的特定场景除外),但在微控制器这样的嵌入式设备上(您的代码是唯一运行的代码),这可能是实现等待外部更改的代码的一种非常有效的方式。正如Acorn在评论中指出的,这当然只有在someVariable
是volatile
(或者不可预测)的情况下才有意义,但是我说的通常是变量上的忙循环。编译器不能在这里提出错误,因为根据C++11标准的第6.5节,这是完全有效的代码。实际上,有两种风格,而
:
while(条件)语句
do语句while(表达式)代码>
语句
可以是
- 一句话或一句话
- 用大括号或括号括起来的语句块
- 空语句(
;
)
考虑到这一点,让我以编译器的方式格式化您的代码:
int main(){
智力状态;
{//刚创建新作用域的大括号块
状态=foo();
}
while(status)/*空语句*/;
}
对于人类读者来说,很明显您想要在花括号中循环代码,但对于编译器来说,这并不明显。这与C++编译器一般不考虑缩进和断线有关。一个考虑到它们的分析工具可能会警告您,您格式化代码的方式与它实际执行的操作不一致,并为您纠正这一点。这会让你更清楚地认识到这个错误。也许有一天我们会有一种语言特性,它允许我们明确地说“空语句”。这将使我们能够清楚地表明我们的意图。一旦我们知道了,编译器可能会在代码不清楚时发出警告。在此之前,我们必须小心——C++是一种强大的语言,但它有一些锋利的边缘……
顺便说一句,你是从缩进/换行中得出错误结论的人
为什么它仍然编译并运行
这不是因为未定义状态
在我看来,编译器应该拒绝这一点,因为这是毫无意义的,或者至少提出一个警告(我的编译器选项中有-Wall)
假设您定义了状态
,则它是一个有效的程序。某些编译器或分析器可能会生成无限循环或无操作的警告,而
体则会生成警告。您自己的解释似乎是正确的。我编译时出错。它抱怨变量status
未声明。您编写的是一个带括号的块,后面跟着一个while
循环,循环体为空。虽然没有警告,因为这可能是完全有效的代码,我敢肯定,像clang tidy这样的静态代码分析器会警告您,循环体中没有更新选中的变量。还要注意的是,-Wall
到目前为止并没有启用所有警告,即使它的名称很不幸。组合-Wall-Wextra
是一个很好的基础,也许最近有更多的警告适合你这样的问题。诊断是一样的。“写一些像while(status);
这样的东西甚至都不是荒谬的”就像写的一样是荒谬的,因为如果status
是真实的,那么它就是荒谬的。优化器可能会假定状态为零,删除循环并开始在foo()上的代码和其他代码上运行。最好说这样的循环必须做一些有意义的事情,或者将状态
标记为易失性
,或者是带有运算符bool的对象
,等等。运算符bool()
也可能有副作用,所以它不像编写while(someVariable)代码>需要外部更改(易失性/原子性)才能退出。而虽然(someFunction())
可以改变牙床,但这就是我一直在寻找的答案。我经常有一行if语句。但我不知道你是谁