这是 C 语言未定义的行为吗?clang 和 GCC 的不同结果

lot*_*tor 2 c gcc side-effects clang unspecified-behavior

对于使用不同编译器的相同代码,我得到了不同的结果。这是一个未定义的行为吗?

#include <stdio.h>
int a;
int b=10;
int puan_ekle(int puan, int bonus){
    puan=puan+bonus;
    a=puan-5;
    bonus--;
    return bonus;
}
int main(){
    a=23;
    printf("Result1 %d \n", a);
    a=a+puan_ekle(a,b);
    printf("Result2 %d \n", a);
    a=a+puan_ekle(a,b);
    printf("Result3 %d \n", a);
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 6

行为是未指定的,不是未定义的。

C 标准区分了这些。C 2018 3.4.4 1 说:

未指明的行为

行为,由使用未指定值引起的行为,或本文档提供两种或多种可能性的其他行为,并且对在任何情况下选择的行为不施加进一步要求

3.4.3 1 说:

未定义的行为

使用不可移植或错误的程序结构或错误数据时的行为,本文档对此不作任何要求

在某些情况下,当对象既用于其值又用于修改时,C 标准中的规则会使行为未定义。6.5 2 说:

如果相对于对同一标量对象的不同副作用或使用同一标量对象的值进行的值计算,标量对象的副作用是未排序的,则行为未定义。如果一个表达式的子表达式有多个允许的排序,并且在任何排序中出现这种未排序的副作用,则行为是未定义的。

让我们看看这如何适用于a=a+puan_ekle(a,b);. 在这个表达式中:

  1. aa=.
  2. a用于a+.
  3. a在参数中使用(a,b)
  4. 在函数内部puan_eklea修改为a=puan-5;

修改是副作用——它们是与计算表达式的值分开发生的事情。如果修改 1 或 4 中的任何一个相对于任何其他项目未排序,则行为未定义。

关于 1, 6.5.16 3 说:

… 更新左操作数的存储值的副作用在左右操作数的值计算之后排序…

所以1在2和3之后被排序。由于4是副作用,不是值计算,我们仍然要考虑1和4的关系。为了解决这个问题,我们将考虑序列点。根据 5.1.2.3,“表达式AB 的计算之间存在序列点意味着与A关联的每个值计算和副作用在与B关联的每个值计算和副作用之前排序。”

接下来我们需要知道什么是完整表达式,以及每个完整表达式后面都有一个序列点。6.8 4 说:

充分表达是不是另一个表达式的一部分,也不是说明符或抽象声明符的一部分的表达...有一个完整的表达式的求值和下一个完整表达的评价之间的序列点进行评估。

这意味着里面的每个语句puan_ekle都是或包含一个完整的表达式:puan=puan+bonus是一个完整的表达式,a=puan-5是一个完整的表达式,bonus--是一个完整的表达式,而bonusinreturn bonus是一个完整的表达式。所以,在 之后a=puan-5,有一个序列点。

因为,对于a=,修改的副作用a是在操作数的值计算之后排序的。评估这些操作数包括调用包含其序列点的函数。因此,修改ain 的效果 4a=puan-5;必须在继续执行下一条语句之前完成,因此必须在效果 1 之前完成。因此 1 和 4 是顺序的。

剩下的是考虑关于 2 和 3 的效果 4。4 在 3 之后排序,因为根据 6.5.2.2 10,函数调用是在评估其参数之后排序的:

在函数指示符和实际参数的计算之后但在实际调用之前有一个序列点......

现在我们只剩下 2 相对于 4 的顺序了。在这里,没有具体说明哪个是第一个。的操作数的计算+是无序的,因此,对于a+puan_ekle(a,b),C 实现可以a先执行,也可以先执行puan_ekle(a,b)。但是,无论它先做什么,在 2 和 4 之间都有一个序列点:

  • 如果a首先评估,则在函数调用之前,有一个序列点(根据 6.5.2.2 10,上面引用)。
  • 如果puan_ekle(a,b)首先计算,则在完整表达式之后有一个序列点a=puan-5

因此,2 和 4 的顺序不确定。(5.1.2.3 3:“……当AB之前或之后排序时,评估AB是不确定的排序,但未指定哪个……”)但它们不是未排序的,因此没有未定义的行为。该行为未指定,因为有两种可能性。C 实现需要实现这两种可能性之一,这与未定义行为不同,在未定义行为中没有要求。