while(cond) // fine
for(;cond;) //fine
但是当我删除条件部分时
while() //syntax compilation error
for(;;) //Infinite loop
这些循环是如何在内部实现的?或者,编译器(解析器)如何知道其中的空条件while
是错误的并且for
是无限的?
我没有特别找到任何关于这个的东西,我认为像我这样的人(他们是初学者)在 C 中可能有同样的困惑
该标准要求将省略的for
循环条件替换为非零常量:
从C11 6.8.5.3开始:(强调我的)
6.8.5.3 for 语句
1 for (clause-1 ; expression-2 ; expression-3 ) 语句的行为如下: 表达式 expression-2 是在每次执行循环体之前计算的控制表达式。每次执行循环体后,表达式 expression-3 被评估为 void 表达式。如果clause-1 是一个声明,它声明的任何变量的范围是声明的其余部分和整个循环,包括其他两个表达式;它在控制表达式的第一次评估之前按照执行顺序到达。如果 Clause-1 是一个表达式,它在控制表达式的第一次评估之前被评估为一个 void 表达式。134)
2 子句 1 和表达式 3 都可以省略。省略的表达式 2 被非零常量替换。
由于循环没有这样的要求while
(如果省略条件),我相信它留给编译器的实现。
没有技术原因可以解释为什么一个有效而另一个无效。这是语言设计者的人为因素考虑。他们觉得无限循环 usingfor (;;)
比while ()
. 他们可能受到了 ALGOL(一种穴居人使用的语言)的影响。
...编译器(解析器)如何知道 while 中的空条件是错误而 for 是无限的?
因为语言定义在语法(语法)和语义上都指定了它。
这是while
循环的语法:
while ( expression ) statement
这是循环的语法for
(截至C2011):
for ( expressionopt ; expressionopt ; expressionopt ) statement
for ( declaration expressionopt ; expressionopt ) statement
语句中 each的下标opt表示对应的表达式是可选的。文本强化了这一点:expressionopt
for
6.8.5.3 for 语句
...
2子句 1和表达式 3都可以省略。省略的表达式 2被非零常量替换。
相比之下,该while
语句的控制表达式没有标记为可选,这在文本中也得到了加强:
6.8.5.1 while 语句
1 控制表达式的计算发生在每次执行循环体之前。
没有太多空间可以解释控制表达式可以省略。
确定程序语法和语义正确性的条件被编码为语言语法。语言语法是由语言创造者制定的,它们决定了语言的外观,就像在 C 的情况下一样。我想背后的基本直觉for(;;)
是while(1)
,任何部分都for(;;)
可以省略,尽管while(1)
对于创建无限循环来说完全足够了,而while()
对于一个狭窄的案例来说,这将是一个骇人听闻的角落案例。
它是 C 语法的一部分。每种编程语言都有其形式语法规范(这里是BNF 中的 C 形式语法- 即在语法上什么是正确的,什么是不正确的。在 C 形式语法中,您可以看到while必须看起来像:
'while' '(' exp ')' 统计
单引号(终端符号)中的单词/符号是强制性的:'while'、'(' 和 ')'。不带引号的词(非终结符号)也是在形式语法中指定的东西。如果你分析 C 形式语法,你会发现 exp不可能是nothing。另一方面,如果您查看for您会看到它可能看起来像:
'for' '(' exp ';' exp ';' exp ')' 统计
| 'for' '(' exp ';' exp ';' ')' 统计
| 'for' '(' exp ';' ';' exp ')' 统计
| 'for' '(' exp ';' ';' ')'stat
| 'for' '(' ';' exp ';' exp ')' 统计
| 'for' '(' ';' exp ';' ')'stat
| 'for' '(' ';' ';' exp ')' 统计
| 'for' '(' ';' ';' ')' 统计
(| 表示或)。
当您编译程序时,词法分析器(编译器的一部分)会检查您的代码在语法上是否正确(即符合形式语法)并根据源代码执行其他操作。