需要帮助理解这对C中的循环代码

考虑C中的以下代码:

void main() { int a=0; for(printf("\nA"); a; printf("\nB")); printf("\nC"); printf("\nD"); } 

当我使用Turb C ++版本3.0和gcc-4.3.4编译它时,我得到以下作为输出的情况:

 A C D 

但是,如果我编译以下代码:

 void main() { for(printf("\nA"); 0; printf("\nB")); printf("\nC"); printf("\nD"); } 

gcc-4.3.4的输出与前一种情况相同,但turbo c ++ 3.0产生以下输出:

 A B C D 

首先,我不知道这里发生了什么! 另外,为什么gcc编译器的输出对于两个代码都是相同的,但在turboc ++ 3.0编译器的情况下,输出是不同的? 有人可以请一些亮点吗?

编辑:

实际上有人在一家IT公司的采访中被问到这个问题,当他没有给出答案时,面试官给出了这个解释。 但我发现这是愚蠢的。 你如何要求某人使用“bug”,好像它是语言提供的“设施”? 因为它被称为“设施”和“技术”,无论我们在第二个表达式中传递0作为文字还是在值为0的变量中传递,结果应该是相同的。

我错误地认为面试官非常愚蠢地提出这样的问题并且表明他的无能?

第二个例子的TCC输出是错误的。

从C99标准:

该声明

for( clause-1 ; expression-2 ; expression-3 语句

表现如下:表达式表达式-2是在每次执行循环体之前计算的控制表达式。 在每次执行循环体之后, 表达式-3被评估为void表达式。 […]

显然,这里没有迭代,所以不应该执行表达式3

同样,在C90标准中(或者至少在我发现的草案中 ),它说:

除了循环体中的continue语句的行为,语句

  for ( expression-1 ; expression-2 ; expression-3 ) statement 

和陈述的顺序

  expression-1 ; while ( expression-2) { statement expression-3 ; } 

是等价的。

Turbo C ++ 3.0在1990年代发布,很快就发布了3.1版本。

我猜你的古代编译器里面有很多bug,它们很快就更新了。 此外,它可能没有这样的错误,但可能已经发出优化的组件,在新的管道衬砌架构下失败。

无论如何, 保证您当前的平台不支持 Turbo C ++ 3.0。 当谈到一个不受支持的编译器,因为该平台是在将近20年后创建的,所以你不能错误地发出错误的程序。

gcc输出是正确的。

第一种情况下的Turbo C ++ 3.0输出是正确的。

第二种情况下的TurboC ++ 3.0输出是错误的。

在Turbo C ++ 3.0编译器中,您似乎找到了一个边缘情况,导致代码生成错误。

C或C ++中的for-stmt具有通用语法

for(初始化;测试;重新初始化)stmt

在循环开始之前,初始化执行一次。 测试在循环的TOP处进行。 如果测试为真,则执行stmt,然​​后重新初始化,循环重复。

在您的情况下,printf(“\ nA”)是初始化,a(或0)是测试,printf(“\ nB”)是重新初始化,stmt是空的。

你应该看过A(你做过)。 测试应该在第一次通过时失败,这意味着你永远不应该看到stmt(但你不知道),你应该永远不会看到B.这是Turbo C ++ 3.0搞砸第二次测试的地方。

C中的完整“for”循环语法是什么(以及它们兼容时的其他语法)?

该问题引用了该标准的适用部分。 除非循环至少执行一次,否则不应评估第3个表达式。 所以,我会说在第二种情况下,旧编译器打印’B’是错误的。

for的语义是第一个表达式被计算(初始化)然后第二个表达式被计算(终止符)然后如果终止符被计算为非零,则执行for的主体,然后计算第三个表达式(advancement)并且回到评估终结者。

由于您没有正文,因此该部分无法评估任何表达式。 基于此,循环应按如下方式执行:

 printf("\nA"); a; // yields 0 -> terminate loop 

确实发生了这种情况。

在你的第二个例子中,同样应该发生(对于gcc ),因为0的计算结果为0。

Turbo C ++ – 看到0常量 – 有可能尝试执行某种循环展开优化(并且未能正确执行)