以下链式赋值是否会导致未定义的行为?

时间:2015-05-18 13:49:54

标签: c undefined-behavior

以下代码是否在C

中调用未定义的行为
int a = 1, b = 2;
a = b = (a + 1);

我知道以下 调用UB:

a = b = a++;

原因是它违反了标准中的以下条款:

  

在前一个和下一个序列点之间,一个对象应该具有它   通过表达式的评估,最多修改一次存储值。   此外,只能访问先前值以确定   值存储。

但是,第一个代码段并未违反此条款。同事说声明a = b = a+1可能意味着

a = a + 1;
b = a + 1;

b = a + 1;
a = b;

我认为由于=的“从右到左”的关联性,它始终必须是a = (b = (a+1)),而不是

a = a + 1;
b = a + 1;
但是,我并不积极。是UB吗?

4 个答案:

答案 0 :(得分:11)

恕我直言,a = b = a+1定义明确。

下面。在a的情况下,您只是使用它来更改 a+1的值。

明确地说,根据=运算符的"right-to-left" associativity,您可以将上述内容细分为,

b = a + 1;  //a does not change here, only the value is used.
a = b;

答案 1 :(得分:4)

这是C99的完整序列点列表(改编自C99,附件C):

  • 在函数调用期间,在评估参数之后以及在执行函数体的任何部分之前;
  • 位于以下运算符的第一个操作数的末尾:&&||?:,;
  • 在完整声明者的末尾;
  • 在完整表达式的末尾(初始化程序,表达式语句中的表达式,return语句中的表达式,for语句中的每个表达式,或{{1的控制表达式},ifswitchwhile声明);
  • 在库函数返回之前;
  • 在与每个格式化的输入/输出函数转换说明符相关联的操作之后;
  • 在每次调用比较函数之前和之后立即;以及对比较函数的任何调用和作为参数传递给该调用的对象的任何移动之间(参考dobsearch()

从这个角度考虑你的代码:

qsort()

有序列点

  1. int a = 1, b = 2; a = b = (a + 1); (完整声明者)之后
  2. a = 1(完整声明者)之后
  3. 在第二个声明的末尾。 (完整的表达)
  4. 整个b = 2是单个表达式语句,它不包含内部序列点。但是,它并没有违反禁止在序列点之间对其值进行多次修改的对象:a = b = (a + 1)a在整个语句中都被修改了一次。

答案 2 :(得分:3)

a = b = a + 1;与:

相同
b = a + 1;
a = b;

您不会更改右侧的左侧值,因此定义良好。

答案 3 :(得分:2)

a = a++;

相比有所不同
a = a+1;

在第二种情况下,您不是通过执行a来修改a+1的值,而在第一种情况下,a的值正在被更改,这将导致未定义的行为。