在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 ++中的每个语句组都被终止
- 分号
- 一个括号
为什么要创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();
循环。 没有这个,就不清楚:
- 什么时候结束?
- 如果while循环之后可能有一个单独的循环,那么在循环之后立即执
这就是为什么我们在do......while
循环结尾join分号,以表示如果条件为假,循环在这里终止。