需要帮助理解C中循环代码的这一点吗

需要帮助理解C中循环代码的这一点吗,c,C,考虑C中的以下代码: void main() { int a=0; for(printf("\nA"); a; printf("\nB")); printf("\nC"); printf("\nD"); } 使用Turb C++版本3和GCC-4.3.4编译时,在以下两个例子中得到如下输出: A C D 但是,如果我编译以下代码: void main() { for(printf("\nA"); 0; printf("\nB"));

考虑C中的以下代码:

void main()
{
    int a=0;

    for(printf("\nA"); a; printf("\nB"));

    printf("\nC");
    printf("\nD");     
}

使用Turb C++版本3和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产生以下输出:

A
B
C
D
首先,我不知道这里发生了什么!另外,为什么gcc编译器的输出对于这两个代码是相同的,但是对于turboc++3.0编译器,输出是不同的?谁能帮我弄点光吗

编辑:

事实上,有人在一家IT公司的面试中被问到这个问题,当他没有给出答案时,面试官给出了这样的解释。但我觉得这很愚蠢。你怎么能要求别人使用一个“bug”,就好像它是该语言提供的一个“工具”?要将其称为“设施”和“技术”,无论我们在第二个表达式中将0作为文本传递,还是作为值为0的变量传递,结果都应该是相同的


我是否错误地认为面试官问这样的问题很愚蠢,这表明他不称职

第二个示例的变矩器离合器输出错误

根据C99标准:

声明

     for (  expression-1 ;  expression-2 ;  expression-3 )  statement
对于(子句-1表达式-2表达式-3语句

     for (  expression-1 ;  expression-2 ;  expression-3 )  statement
行为如下:表达式-2是控件 在每次执行循环体之前计算的表达式。 表达式-3在 循环体的每次执行。[……]

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

类似地,在C90标准中(或至少在a中),它表示:

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

     for (  expression-1 ;  expression-2 ;  expression-3 )  statement
以及陈述的顺序

      expression-1 ;
     while ( expression-2) {
               statement
              expression-3 ;
     }
它们是等价的


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

< P> Turbo C++ 3在1990版本中被释放,很快地被跟踪,释放了3.1。 我猜你的古代编译器中有很多bug,更新得很快。此外,它可能没有这样的bug,但可能发出了优化的组装,在新的管道衬里架构下失败


在任何情况下,它都是<强>保证< /强>在当前平台上不支持Turbo C++ 3。当涉及到由于平台创建时间将近20年而不受支持的编译器时,你不能因为它发出了错误的程序而指责它。

for的
语义是先计算第一个表达式(初始值设定项),然后再计算第二个表达式(终止项)然后,如果终止符计算为非零,则执行for的主体,然后计算第三个表达式(高级)并返回到计算终止符

因为您没有实体,所以该部分等于没有计算表达式。基于此,循环应按如下方式执行:

printf("\nA");
a; // yields 0 -> terminate loop
事实就是这样

在第二个示例中,当0计算为0时,应该发生相同的情况(对于gcc也是如此)


< Turbo C++可能是——看到0常数——试图执行某种循环展开优化(并且没有正确地完成)

< P> GCC输出是正确的。< /P>

第一种情况下的Turbo C++ 3输出是正确的。 第二种情况下的TurboC++3.0输出错误

您似乎发现了一个边缘情况,导致Turbo C++ 3编译器中错误代码生成。

在C或C++中,STMT的一般语法

用于(初始化;测试;重新初始化)stmt

初始化在循环开始之前执行一次。测试在回路顶部执行。如果测试为真,则执行stmt,然后重新初始化,循环重复

在您的例子中,printf(“\nA”)是初始化,a(或0)是测试,printf(“\nB”)是重新初始化,stmt是空的


你应该看看A(你确实看到了)。在第一次测试中,测试应该失败了,这意味着你不应该看到STMT(但你不知道),你永远也不应该看到B。这是Turbo C++ 3在第二次测试中搞砸的地方。但是,你究竟为什么要首先对
循环使用那种
?@ThomasPadron McCarthy实际上,语法很好。它似乎没有什么用处,但却完全有效,正如“我的感冒是脚趾”这句话在语法上完全有效,但却是一个毫无意义的短语。第一部分,
printf(“\nA”)
,将在循环开始时执行;sentinel表达式导致循环在计算结果为false/0时停止执行,第一个表达式为
a
(它==0),第二个表达式为literal
0
;[cont.]@Naveen:很明显,在它里面发现奇怪的bug是很困难的。[cont.]最后一部分,
printf(“\nB”)
,通常在循环的每个迭代结束时执行,不应该执行,因为sentinel的计算结果是0,在3/4的情况下是这样的。这是一个编译器bug。在10年前和更年前,人们可以在网上发现更多类似的问题,如“代码> Turbo C++ 3 <代码>。(;0;)语句的偶数
使
语句
执行。请注意,TC++3.0源于一个时代,当时大多数DOS编译器都不符合标准,甚至实现了不可压缩的扩展,只是为了将用户锁定(例如。