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

时间:2012-06-18 16:08:48

标签: 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的变量中传递,结果应该是相同的。

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

5 个答案:

答案 0 :(得分:12)

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

来自C99标准:

  

声明

     

for( clause-1 ; expression-2 ; 表达式3 声明

     

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

显然,这里没有迭代,所以永远不应该执行 expression-3

同样,在C90标准中(或至少在draft that I found中),它表示:

  

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

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

和陈述序列

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

是等价的。

答案 1 :(得分:3)

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

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

无论如何,保证在您当前的平台上不支持 。当谈到一个不受支持的编译器,因为该平台是在将近20年后创建的,所以你不能因为发出错误的程序而对它进行错误的判断。

答案 2 :(得分:2)

gcc输出正确。

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

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

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

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

  

for(initialization; test; reinitialization)stmt

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

在你的情况下,printf(" \ nA")是初始化,a(或0)是测试,printf(" \ nB")是重新初始化,并且stmt是空的。

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

答案 3 :(得分:1)

What is the full "for" loop syntax in C (and others in case they are compatible)?

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

答案 4 :(得分:1)

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

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

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

确实会发生这种情况。

在你的第二个例子中,同样的事情应该发生(就像 gcc 一样),因为0评估为0。

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