繁体   English   中英

为什么GCC和Clang的结果与以下代码不同?

[英]Why results of GCC and Clang are different with following code?

对于以下使用gcc和clang的代码,我得到了不同的结果,我相信这不是一个严重的错误,但是我想知道哪个结果与标准更一致? 非常感谢您的回复。

我使用gcc(Ubuntu 7.3.0-27ubuntu1〜18.04)7.3.0和clang版本6.0.0-1ubuntu2(tags / RELEASE_600 / final)

#include <stdio.h>
int get_1(){
        printf("get_1\n");
        return 1;
}
int get_2(){
        printf("get_2\n");
        return 2;
}
int get_3(){
        printf("get_3\n");
        return 3;
}
int get_4(){
        printf("get_4\n");
        return 4;
}
int main(int argc, char *argv[])
{
        printf("%d\n",get_1() + get_2() - (get_3(), get_4()));
        return 0;
}

gcc的结果是

get_3
get_1
get_2
get_4
-1

of的结果是

get_1
get_2
get_3
get_4
-1

C在评估某些运算符的操作数时不施加顺序。 在C标准中,评估的顺序由顺序点决定 当存在序列点时,该语言的良好实现必须先评估序列点左侧的所有内容,然后才能开始评估右侧的内容。 +-运算符不包含任何序列点。 这是5.1.2.3 p2的定义

在执行序列中某些特定的点(称为顺序点)上,以前评估的所有副作用都应完整,并且以后评估的副作用都不应发生。

在你的表情

get_1() + get_2() - (get_3(), get_4())

你有+-和逗号,运营商。 只有逗号强加了一个计算顺序,而+-则没有。

,之间get_3()get_4()是在唯一的序列点printf("%d\\n",get_1() + get_2() - (get_3(), get_4())); 只要get_3()get_4()之前发生,就可以按照编译器定义的任何顺序进行get_x调用。

您正在看到未指定行为的结果。

有两个不同但相关的术语在起作用: 运算符优先级求值顺序

运算符优先级指示解析顺序:

  • 在您的表达式中,括号的优先级最高,因此括号内的内容属于同一类。
  • 接下来,我们有函数调用operator () 没什么奇怪的,它们是后缀,属于它们的运算符,即函数名。
  • 接下来,我们有二进制+-运算符。 它们属于同一运算符组“加法运算符”,并且具有相同的优先级。 发生这种情况时,该组操作员的操作员关联性决定了应按哪个顺序解析他们。

    对于加法运算符,运算符的关联性是从左到右。 这意味着该表达式可以保证被解析为(get_1() + get_2()) - ...

  • 最后,我们得到了奇数逗号运算符,其优先级最低。

一旦按以上方法算出了运算符优先级,我们便知道哪些运算数属于哪些运算符。 但这并没有说明表达式将按什么顺序执行。 这就是评估顺序的来源。

通常,C用干燥的标准术语表示:

除非后面有说明,否则子表达式的副作用和值计算是不排序的。

用简单的英语来说,这意味着在大多数情况下,操作数的评估顺序是不确定的,但有一些特殊的例外。

对于加法运算符+- ,这是正确的。 给定a + b我们不知道ab将首先执行。 评估的顺序是不确定的-编译器可以按自己喜欢的任何顺序执行它,不需要记录如何做,甚至不必视情况而定。

C标准有意将此保留为未指定,以允许不同的编译器以不同的方式解析表达式。 本质上是允许他们将其表达式树算法保留为编译器商业秘密,以允许某些编译器在自由市场上比其他编译器产生更有效的代码。

这就是为什么gcc和clang给出不同结果的原因。 您已经编写了依赖于评估顺序的代码。 这都不是任何编译器的错-我们不应该简单地编写依赖于行为不当的程序。 如果必须按一定顺序执行这些功能,则应将它们分成几行/多个表达式。

对于逗号运算符,这是罕见的特殊情况之一。 它带有一个内置的“序列点”,该序列点确保始终在对左操作数进行求值(执行)之前将其赋值。 其他此类特殊情况是&& || 运算符和?:运算符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM