在C语言中,使用条件语句而非赋值语句作为for循环头的第一部分

4

2
这是一个重要的历史代码构建,被称为“错误”。作者本意是防止i减少到零以下(或小于-1),但编写了错误的代码,因此完整的意图不清楚。 - Eric Postpischil
@Jabberwocky 这段代码到底是干什么的?我以前从未见过。在Java中是不允许的。 - Michael
@madcobra Java不是C语言。请参考下面的回答。 - Jabberwocky
K&R(任意版本)是学习C语言示例的丰富来源,比其他任何地方都要好。他们坚持使用干净、简洁和易读的风格,并有许多示例展示了惯用的速记法如何提高程序的可读性。 - mevets
2个回答

4
为什么C语言允许这样的语法?
为什么不能允许呢?在一个for循环中,初始值可以是一个表达式、一个声明,或者为空。像其他任何表达式一样,“i>0”也是一个表达式。为了达到小幅度地简化语言的效果而限制其它可用的表达式会使语言更加复杂。
如果编译器愿意,为这种奇怪的代码发出警告是实现质量问题。
那么这段代码有什么作用呢?
绝对没有作用(除非“i”被定义为执行某些操作的宏)。编译器将忽略这段代码。

3

for语句的第一个子句可以是声明,也可以是(在本例中)空上下文中的表达式。这意味着第一个子句会被求值以获取其副作用,通常是赋值,它是一种表达式。

C标准的6.8.5.3节如下定义for语句:

1 语句

for (子句1; 表达式2; 表达式3) 语句

的行为如下:表达式 expression-2 是控制表达式,在每次执行循环体之前计算。表达式 expression-3 是在每次执行循环体之后作为无效表达式计算。如果 clause-1 是一个声明,则它所声明的任何标识符的范围是声明的其余部分和整个循环,包括其他两个表达式;它在第一次评估控制表达式之前按执行顺序到达。如果 clause-1 是一个表达式,则在第一次评估控制表达式之前将其作为无效表达式计算。

2 子句1和表达式3都可以省略。省略的表达式2将被替换为非零常数。

for 语句的第一个子句中,允许使用任何表达式。在这种情况下,表达式 i > 0 被计算但没有副作用,因此它实际上什么也没做。这与以下代码相同:

for (; ((s[i] == ' ') || (s[i] == '\t')); --i)

不太喜欢副作用。密集编程+副作用可能不会执行。 - Michael
1
@madcobra 从技术上讲,C语言中的任何赋值都是副作用,因为赋值表达式会取得被赋的值(实际的赋值是副作用),所以你可以这样做:if ((result=foo()) == 0) - dbush
这是我讨厌 C 的另一件事。我在书中早就遇到了这个特性,然后写下了“哎呀,好代码”的注释。我应该关闭这本 C 书,回到 Java 哈哈。 - Michael

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