在C/C++中为什么要做while(表达式); 需要半结肠?

jus*_*nhj 35 c c++ language-design

我的猜测是它只是简化了解析,但我看不清楚原因.

那么这有什么......

do
{
  some stuff
}
while(test);

more stuff
Run Code Online (Sandbox Code Playgroud)

那比...更好

do
{
  some stuff
}
while(test)

more stuff
Run Code Online (Sandbox Code Playgroud)

Joe*_*ite 57

因为你要结束陈述.语句以块(由大括号分隔)或分号结束."执行此操作时"这是一个单独的语句,并且不能以块结尾(因为它以"while"结尾),因此它需要一个分号,就像任何其他语句一样.

  • @Matthias:但它以花括号结束. (12认同)
  • 接受的答案只是做出了一个不同的断言,你直观地认为它是"正确的"和"明确的例子",而事实上它绝对是不正确的.如果语法不同,你认为会出现的问题实际上不会出现. (7认同)
  • 如果看起来像是试图在没有它的情况下编写语法.由于语句可以嵌套,因此需要定义分隔符.在C/C++中,这是';'. (5认同)

AnT*_*AnT 30

如果你看一下C++语法,你会看到迭代语句被定义为

而( 条件 ) 陈述

for( for-init-statement condition -opt ; expression -opt ) statement

声明 而( 表达 );

请注意,只有do-while语句最后有一个;.所以,问题是为什么do-while它与其他部分如此不同,以至于它需要额外的;.

让我们来仔细看看:既for和定期while与结束发言.但do-while带有控制结束表达封入().封闭的存在()已经允许编译器明确地找到控制表达式的结尾:外部闭合)指定表达式结束的位置,因此指定整个do-while语句结束的位置.换句话说,终止;确实是多余的.

但是,在实践中,这意味着,例如,以下代码

do
{
  /* whatever */
} while (i + 2) * j > 0;
Run Code Online (Sandbox Code Playgroud)

虽然从语法的角度来看是有效的,但实际上会被解析为

do
{
  /* whatever */
} while (i + 2)

*j > 0;
Run Code Online (Sandbox Code Playgroud)

这是正式的声音,但它并不是非常直观.我猜想由于这些原因,决定在do-while语句中添加一个更明确的终结符- 分号.当然,根据@Joe White的回答,还要考虑简单和简单的一致性:C中的所有普通(非复合)语句都以a结尾;.

  • +1是唯一正确的答案,如果不需要分号就会出现"坏"的真实例子. (7认同)
  • @justinhj:不,绝对不对.接受的答案令人困惑,因为它暗示了一些"不同的行为",但未能解释这些行为会是什么.预计,正如你自己可以很容易地看到的那样,当他认为没有分号要求内部`while`语句会与外部`do`错误关联时,其中一位接受回答的评论者实际上感到困惑.这根本不是真的.语法是专门设计的,不会让这种情况发生,分号或不分号. (3认同)
  • @Tony:AndreyT的回答并不意味着表达一种含糊不清的东西 - 正如它所说的那样,因为必须使用parantheses,解析不是*模糊不清 - 它只是潜在的不直观. (3认同)

小智 24

这是因为while语句在do-while循环中是有效的.

如果不需要分号,请考虑不同的行为:

int x = 10;
int y = 10;

do 
  while(x > 0)
    x--;
while(x = y--);
Run Code Online (Sandbox Code Playgroud)

  • do和while之间没有指令的事实足以让编译器找到"end of do"和"new loop"之间的区别.你的例子很有趣,但我不认为这解释了为什么在做了之后会有分号. (24认同)
  • onebyone:不对.`do while(...);`不合法.一个空的`do-while`循环写成:`do; while(...);`或`do {} while(...);`它不会编译. (8认同)
  • 这个答案是错误的 - `do while(x> 0)x - ;`*不能被误解为一个控制表达式为"x> 0"的空循环,后跟一个`x - ;`语句.这是因为空循环*必须*写成`do; while(expr)`或`do {} while(expr)` - 循环体必须是一个语句. (6认同)
  • -1.这个例子似乎暗示如果没有尾随`;`要求,代码会以某种方式被误解.实际上,语言语法(即使是当前形式)也不允许任何涉嫌误解上述代码,即使删除了尾随的";"要求.Benoît是对的:这个例子没有解释与这个问题有关的任何事情.这个答案是不正确的.我允许Don暗示我缺少的东西,但直到他澄清他的意思,这是一个坚实的-1. (5认同)
  • @Steve:在C++和C中,`do while(x)`不合法:你必须使用`do; while(x)`或do {} while(x)`.Benoît和AndreyT是正确的. (3认同)
  • 一个更好的例子:`do f(); while(x ++)g(); while(y ++)h();`.哪个`while`终止`do`? (2认同)

Jar*_*Par 9

虽然我不知道答案,但一致性似乎是最好的论据.C/C++中的每个语句组都以

  1. 分号
  2. 支撑

为什么要创建一个既不会执行的构造

  • @Rocketmagnet,你不能允许所有语句(包括null语句),因为"void f();" (带有"null语句"作为主体的函数定义)与"void f();"不同 (仅限功能声明).两者看起来都一样.要求复合语句是一件好事.无论如何,函数定义不是声明. (6认同)

Ton*_*roy 6

流控制语句的一致性

考虑到一致性......

if (expr) statement;
do statement; while (expr);
for (expr; expr; expr) statement;
while (expr) statement;
Run Code Online (Sandbox Code Playgroud)

......所有这些流控制结构,以分号结尾.

但是,反驳我们可以注意到块语句形式,只有do while以分号分隔:

if (expr) { ... }
do { ... } while (expr);
for (expr; expr; expr) { }
while (expr) { }
Run Code Online (Sandbox Code Playgroud)

所以,我们有';' 或'}',但绝不是"裸"')'.

语句分隔符的一致性

我们至少可以说每个语句都必须用;or 分隔},并且在视觉上可以帮助我们区分语句.

如果不需要分号,请考虑:

do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4;
Run Code Online (Sandbox Code Playgroud)

在视觉上将其解析为不同的语句是非常困难的:

do statement1; while (expr1)
statement2;
do ; while (expr2)
statement3;
while (expr3) statement4;
Run Code Online (Sandbox Code Playgroud)

相比之下,以下内容更容易解决,因为;while条件告诉您向后寻找后do,并且下一个语句与之无关while:

do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4;
Run Code Online (Sandbox Code Playgroud)

是否重要,因为人们缩进他们的代码以使流程可以理解?是的,因为:

  • 人们有时会犯错误(或者在代码被按摩时暂时出现错误),如果它在视觉上突出显示意味着它将更容易修复,并且
  • 宏替换可以在一行上抛出大量语句,我们偶尔需要在排除故障或进行QA时直观地验证预处理器输出.

对预处理器使用的影响

值得注意的是着名的预处理器do-while成语:

#define F(X) do { fn(X); } while (false)
Run Code Online (Sandbox Code Playgroud)

这可以替换如下:

if (expr)
    F(x);
else
    x = 10;
Run Code Online (Sandbox Code Playgroud)

... ...产量

if (expr)
    do ( fn(x); } while (false);
else
    x = 10;
Run Code Online (Sandbox Code Playgroud)

如果分号不是do while语句的一部分,则该if语句将被解释为:

if (expr)
    do-while-statement
; // empty statement
else
    x = 10;
Run Code Online (Sandbox Code Playgroud)

...并且,因为在if它之后有两个语句,它被认为是完整的,这使得else语句无法比拟.