在for循环和while循环中没有循环条件

10
while(cond) // fine
for(;cond;) //fine

但是当我删除条件部分时

while() //syntax compilation error 
for(;;) //Infinite loop
这些循环是如何在内部实现的? 或者说,编译器(解析器)如何知道while中的空条件是错误的,而在for中是无限的?
我没有找到关于这个问题的特别内容,我认为像我一样(初学者)的C语言使用者可能会有同样的困惑。

1
编译器知道这是因为它们已经被定义好了。 - Jasper
5个回答

12
标准要求 for 循环中省略条件的需用非零常量替换:
来源于 C11 6.8.5.3 :(重点标出)
“6.8.5.3 for 语句 1. 语句 for (clause-1; expression-2; expression-3) statement 的行为如下:表达式 expression-2 是控制表达式,会在执行循环体之前对其进行评估。表达式 expression-3 在执行循环体后作为 void 表达式对其进行评估。如果 clause-1 是声明,则它所声明的任何变量的作用域都是该声明的余下部分和整个循环,包括另外两个表达式;在第一次评估控制表达式之前按照执行顺序到达。 如果 clause-1 是表达式,则在第一次评估控制表达式之前将其作为 void 表达式进行评估。(134)
2. 可以省略 clause-1 和 expression-3。省略 expression-2 将被替换为非零常量。”
由于 while 循环没有这样的要求(如果省略条件),我认为这取决于编译器的实现。

3
因为语言定义在语法和语义上都指定了,在while循环中用空条件是错误的,而在for循环中则是无限的。以下是while循环的语法:
<strong>while (</strong> <em>expression</em> <strong>)</strong> <em>statement</em>

下面是一个for循环的语法(截至C2011):

<strong>for (</strong> <em>expression<sub>opt</sub></em> <strong>;</strong> <em>expression<sub>opt</sub></em> <strong>;</strong> <em>expression<sub>opt</sub></em> <strong>)</strong> <em>statement</em>
<strong>for (</strong> <em>declaration expression<sub>opt</sub></em> <strong>;</strong> <em>expression<sub>opt</sub></em> <strong>)</strong> <em>statement</em>

每个for语句中的expressionopt中的下标opt表示相应的表达式是可选的。这一点在以下文本中得到了强化:

6.8.5.3 for语句

...
2 clause-1expression-3都可以省略。省略的expression-2将被替换为非零常量。
相比之下,while语句的控制表达式没有被标记为可选,这也在以下文本中得到了强化:

6.8.5.1 while语句

1 在执行循环体之前,对控制表达式进行评估。
在这里没有太多解释控制表达式可以省略的空间。

3

没有技术原因可以解释为什么一个有效而另一个无效。这是语言设计者的人类因素考虑。他们认为使用 for (;;) 的无限循环比使用 while () 更有意义。他们可能受到早期语言 ALGOL 的影响。


2
程序的语法和语义正确性条件被编码到语言语法中。语言语法由语言创建者制定,它们决定了语言的外观和感觉,就像在C语言的情况下一样。 我认为for(;;)while(1)背后的基本直觉是,for(;;)的任何部分都可以省略,而while(1)完全足够创建无限循环,然而while()只是一个狭窄情况的hacky角落。

2
这是C语言语法的一部分。每种编程语言都有其正式的语法规范(这里是C语言BNF格式),即什么是语法正确的,什么不是。在C语言的正式语法中,可以看到while必须像下面这样:

'while' '(' exp ')' stat

单引号中的单词/符号(终端符号)是必需的:'while'、'('和')'。 非引用的单词(非终端符号)也在正式语法中指定了。如果你分析了C语言的正式语法,就会发现exp不能为nothing。另一方面,如果你看看for,就会发现它可以像下面这样:

'for' '(' exp ';' exp ';' exp ')' stat

| 'for' '(' exp ';' exp ';' ')' stat

| 'for' '(' exp ';' ';' exp ')' stat

| 'for' '(' exp ';' ';' ')'stat

| 'for' '(' ';' exp ';' exp ')' stat

| 'for' '(' ';' exp ';' ')'stat

| 'for' '(' ';' ';' exp ')' stat

| 'for' '(' ';' ';' ')' stat

(|表示OR)。
编译程序时,词法分析器(编译器的一部分)检查您的代码是否符合语法(即符合正式语法),并根据源代码执行其他操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接