C:当GCC从右到左评估时,为什么LLVM从左到右评估printf?

时间:2014-09-04 15:33:49

标签: c gcc printf clang operator-precedence

如本问题所述:LLVM and GCC, different output same code,LLVM和GCC导致相同代码的输出不同。

#include <stdio.h>

#define MAX(a,b) ( (a) > (b) ? (a) : (b) )

int increment() {
    static int i = 42;
    i += 5;
    printf("increment returns %d\n",i);
    return i;
}

int main( int argc, char ** argv ) {
    int x = 50;
    printf("max of %d and %d is %d\n", x,increment(),MAX(x, increment()));
    printf("max of %d and %d is %d\n", x,increment(),MAX(x, increment()));
    return 0;
}

LLVM输出给出:

increment returns 47
increment returns 52
increment returns 57
max of 50 and 47 is 57
increment returns 62
increment returns 67
increment returns 72
max of 50 and 62 is 72

而GCC输出给出:

increment returns 47
increment returns 52
max of 50 and 52 is 50
increment returns 57
increment returns 62
increment returns 67
max of 50 and 67 is 62

现在,在另一个问题中,有人回答说没有指定参数的评估顺序,这就是未指定行为的原因。但是,如果仔细检查代码,可以看到实际上指定了评估顺序。 GCC编译器从右到左从x,increment(),MAX(x, increment())方法评估printf(),而LLVM编译器从左到右评估此代码。有谁知道为什么会这样?不应该像printf的评估顺序那样清楚地定义,对于两个编译器都是一样的吗?

另外,我只是想澄清一下,这段代码来自一个教程,旨在了解C语言的工作原理。它的目的不是成为一个正常工作的程序,也不是一个准确的输出。古怪的输出是有意的,因此使用像代码中使用的傻宏(MAX)。我只是想了解为什么这里有这么大的差异,谢谢!

1 个答案:

答案 0 :(得分:9)

函数参数的评估顺序不是由规范定义的。编译器可以按照他们喜欢的顺序自由评估。仅仅因为特定实现以一致的方式执行它并不会改变两个不同实现可能具有不同行为的事实。

如果您需要来自不同编译器的一致输出,则需要根据标准编写具有明确定义的行为的代码。