在C / C ++中,为什么while(expression式); 需要一个分号?

我的猜测是它只是使parsing更容易,但我不明白为什么。

那么这有什么…

do { some stuff } while(test); more stuff 

这比…好

 do { some stuff } while(test) more stuff 

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

考虑不同的行为,如果分号不是必需的:

 int x = 10; int y = 10; do while(x > 0) x--; while(x = y--); 

因为你正在结束这个声明。 一个语句以一个块(用大括号分隔)或一个分号结束。 “这样做,”这是一个单一的陈述,不能结束一个块(因为它以“while”结束),所以它需要一个分号就像任何其他语句。

如果你看看C ++语法,你会发现迭代语句被定义为

同时( 条件 声明

for( for-init-statement condition -opt ; expression -opt 语句

expression );

请注意,只有do-while语句有一个; 最后。 所以,问题是为什么do-while和其他的不一样,它需要额外的;

让我们仔细看一下:既有正常的for也有正常的while最后是一个声明 。 但是, do-while()的控制expression式结束。 那个enclosing ()的存在已经允许编译器明确地find控制expression式的结尾:外部closures)指定了expression式结束的地方,并且因此指明了整个do-while语句结束的地方。 换句话说,终止; 确实是多余的。

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

 do { /* whatever */ } while (i + 2) * j > 0; 

而从语法的angular度来看,真正被parsing为

 do { /* whatever */ } while (i + 2) *j > 0; 

这是正式的,但并不直观。 我猜测出于这样的原因,决定在do-while语句中添加一个更明确的终止符 – 分号。 当然,根据@Joe White的回答,也有简单一致性的考虑:C中的所有普通(非复合)语句以a ;

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

  1. 分号
  2. 一个括号

为什么要创build一个既不兼容?

stream程控制语句一致性

考虑到一致性…

 if (expr) statement; do statement; while (expr); for (expr; expr; expr) statement; while (expr) statement; 

…所有这些stream控制结构,以分号结尾。

但是,反过来说我们可以注意到块声明的forms,只能用分号分隔:

 if (expr) { ... } do { ... } while (expr); for (expr; expr; expr) { } while (expr) { } 

所以,我们有';' 或'}',但从来没有“裸”')'。

语句分隔符的一致性

我们至less可以说,每一个陈述都必须由…划定;} ,在视觉上帮助我们区分语句。

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

 do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4; 

直观地解决这些不同的陈述是非常困难的:

 do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4; 

相反,以下更容易解决为一个; 在一段while之后立即告诉你为这个do倒退,并且下一个陈述与那个没有联系:

 do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4; 

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

  • 人们有时候会犯错误(或者像代码被按摩一样短暂地),如果它在视觉上突出,意味着它会被更容易地修复,
  • macrosreplace可以将大量语句放在一行上,偶尔还需要在排除故障或执行QA时直观地validation预处理器输出。

对预处理器使用的影响

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

 #define F(X) do { fn(X); } while (false) 

这可以被replace如下:

 if (expr) F(x); else x = 10; 

… …产量

 if (expr) do ( fn(x); } while (false); else x = 10; 

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

 if (expr) do-while-statement ; // empty statement else x = 10; 

…因为在if之后有两个语句,所以它被认为是完成的,这使得else语句不能匹配。

C是分号终止的(而Pascal是分号分隔的)。 把分号放在那里是不一致的。

坦率地说,我恨这个循环的重用。 我想重复一遍,直到不会那么困惑。 但是它就是这样啊。

在C / C ++的空白不参与结构(如在Python中)。 在C / C ++语句中, 必须以分号结尾。 这是允许的:

 do { some stuff; more stuff; even more stuff; } while(test); 

我的答案是,编译器可能会混淆,当我们在终止时不包括分号do.....while(); 循环。 没有这个,就不清楚:

  1. 什么时候结束?
  2. 如果while循环之后可能有一个单独的循环,那么在循环之后立即执

这就是为什么我们在do......while循环结尾join分号,以表示如果条件为假,循环在这里终止。