序列点和副作用:C11的安静变化?

maf*_*fso 14 c c99 undefined-behavior sequence-points c11

C99§6.5 表达式

(1)表达式是操作符和操作数的序列,其指定值的计算,或指定对象或函数,或者生成副作用,或执行其组合.

(2)在前一个和下一个序列点之间,一个对象的存储值最多只能通过表达式的评估来修改一次.72)此外,先前值应只读以确定要存储的值.73)

用脚注

72)浮点状态标志不是对象,可以在表达式中多次设置.

73)此段落呈现未定义的语句表达式,如

    i = ++i + 1;
    a[i++] = i;
Run Code Online (Sandbox Code Playgroud)

允许的同时

    i = i + 1;
    a[i] = i;
Run Code Online (Sandbox Code Playgroud)

C11§6.5改为((1)的文本有附录):

(1)[...]运算符的操作数的值计算在运算符的结果的值计算之前被排序.

(2)如果对标量对象的副作用相对于对同一标量对象的不同副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.如果表达式的子表达式有多个允许的排序,则如果在任何排序中发生这种未测序的副作用,则行为是不确定的.84)

C11中的脚注84与C99中的73相同.

我有点困惑......我把C11(2)读作"[...](对同一标量对象的不同副作用)或(使用相同标量对象的值进行值计算)[...]"似乎甚至不允许foo = ++i(有副作用,我们根据更改的对象使用值).不过,我不是母语人士,所以如果能告诉我这句话应该如何"解析"会更好.我理解C99,但我不太明白C11的措辞.

无论如何,实际问题:这是从C99到C11的变化,还是这些措辞相当?如果是这样,为什么它会被改变?如果没有,有人可以给出一个表达式的例子,这个表达式在C99中是UB而在C11中不是,反之亦然?

Jen*_*edt 5

C11(还有 C++11)完全修改了排序的措辞,因为 C11 现在有线程,并且它必须解释访问相同数据的线程之间的排序意味着什么。该委员会的目的是在只有一个执行线程的情况下保持与 C99 的向后兼容。

我们看一下C99版本:

  1. 上一个序列点和下一个序列点之间

  2. 一个东西

  3. 应有

  4. 其存储值最多修改一次

  5. 通过表达式的求值。

与新文本相比

如果有副作用

4、修改存储值的不同术语

标量对象

对 2 中先前措辞的限制。新文本仅说明有关标量对象的内容

相对于任一者都是无序的

unsequenced 是 1. 中概念的概括,即两个语句由序列点分隔。想象两个线程修改相同的数据而不使用锁或类似的东西。

对同一标量对象的不同副作用

该对象只允许修改一次

或使用同一标量对象的值进行值计算,

或者对值的读取可能不会与修改同时出现

该行为是未定义的。

3.中的“应当”含蓄地表达了这一点。如果未满足所有“应”,则将导致 UB。