此 C 代码会导致未定义行为吗?

问题描述

我知道:

int b = 1,c = 2,d = 3,e = 4;
printf("%d %d %d",++b,b,b++);

导致未定义的行为。由于

在两个序列点之间多次修改任何对象是 UB。 Undefined behavior and sequence points

但我不知道:

int b = 1,e = 4;
printf("%d",b++ + ++c - --d - e--);

也是UB吗?

我认为递增/递减运算符将首先评估,因为它们之间的优先级从右到左,因为 associativity 。然后算术运算符将从左到右求值。

就是这样

(b) + (c + 1) - (d - 1) - (e)

即 1 + (2 + 1) - (3 - 1) - (4)

= (2 - 4)

= -2

对吗?

解决方法

但我不知道:...也是UB吗?

不是,但您对原因的推理是模糊的。

我认为增量/减量运算符将首先评估,因为它们之间的优先级从右到左,因为 associativity 。然后算术运算符将从左到右求值。

优先级决定了结果的计算方式。它没有说明副作用的顺序。

没有等效的优先级告诉您在语句期间何时可以观察到副作用(b 的存储值已增加,e 的存储值已减少)是可观察的 。您只知道变量在 next 语句之前(即通过 ;)采用了新值。

所以,这是明确定义的原因是它不依赖于那些副作用


为了避免陷入困境,我故意用手挥舞着语言,但我可能应该澄清一下:

  • 在语句中”的意思是“在下一个序列点之前
  • “在 next 语句之前 (... ;)”真正的意思是“在下一个序列点

Order of evaluation

  1. 在对所有函数参数和函数指示符求值之后,实际函数调用之前,有一个序列点。

所以真的副作用是在调用 printf 之前提交的,所以比语句末尾的 ; 早。

,

表达之间存在巨大差异

b++ + ++c - --d - e--

(这很好),以及

x++ + ++x - --x - x--

(这是大量未定义的)。

不是使用 ++-- 使表达式未定义。它甚至不会在同一个表达式中使用 ++-- 两次。不,问题是当您使用 ++-- 修改表达式中的变量时,并且您还尝试在相同的其他地方使用相同变量的值表达式,并且没有中间序列点。

考虑更简单的表达

++z + z;

现在,显然子表达式 ++z 将增加 z。所以问题是,+ z 部分是使用 z 的旧值还是新值?答案是没有答案,这就是为什么这个表达式是未定义的。

请记住,像 ++z do not 这样的表达式只是表示“取 z 的值并加 1”。它们的意思是“取 z 的值并加 1,然后将结果存回 z”。这些表达式具有副作用。而副作用是不确定性问题的根源。