C++ 忘了做在做。。。while循环

C++ 忘了做在做。。。while循环,c++,C++,我有一个恼人的bug,我忘了在do中写do。。。而循环 int main() { int status=1; /*do*/ { status = foo(); } while (status); } 为什么它仍然编译并运行?在我看来,编译器应该以无意义为由拒绝这一点,或者至少发出警告(我的编译器选项中有-Wall)。我正在使用C++11 据我所知,带括号的代码运行{…},然后程序无限检查while子句中的条件。我假设您实际上在循环体之外有int status,否则代码将无法

我有一个恼人的bug,我忘了在
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语句。但我不知道你是谁