什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
#include <stdio.h>
int main(void)
{
int i = 0;
i = i++ + ++i;
printf("%d\n", i); // 3
i = 1;
i = (i++);
printf("%d\n", i); // 2 Should be 1, no ?
volatile int u = 0;
u = u++ + ++u;
printf("%d\n", u); // 1
u = 1;
u = (u++);
printf("%d\n", u); // 2 Should also be one, no ?
register int v = 0;
v = v++ + ++v;
printf("%d\n", v); // 3 (Should be the …Run Code Online (Sandbox Code Playgroud) c increment operator-precedence undefined-behavior sequence-points
C99§6.5 表达式
(1)表达式是操作符和操作数的序列,其指定值的计算,或指定对象或函数,或者生成副作用,或执行其组合.
(2)在前一个和下一个序列点之间,一个对象的存储值最多只能通过表达式的评估来修改一次.72)此外,先前值应只读以确定要存储的值.73)
用脚注
72)浮点状态标志不是对象,可以在表达式中多次设置.
73)此段落呈现未定义的语句表达式,如
Run Code Online (Sandbox Code Playgroud)i = ++i + 1; a[i++] = i;允许的同时
Run Code Online (Sandbox Code Playgroud)i = i + 1; a[i] = i;
C11§6.5改为((1)的文本有附录):
(1)[...]运算符的操作数的值计算在运算符的结果的值计算之前被排序.
(2)如果对标量对象的副作用相对于对同一标量对象的不同副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.如果表达式的子表达式有多个允许的排序,则如果在任何排序中发生这种未测序的副作用,则行为是不确定的.84)
C11中的脚注84与C99中的73相同.
我有点困惑......我把C11(2)读作"[...](对同一标量对象的不同副作用)或(使用相同标量对象的值进行值计算)[...]"似乎甚至不允许foo = ++i(有副作用,我们根据更改的对象使用值).不过,我不是母语人士,所以如果能告诉我这句话应该如何"解析"会更好.我理解C99,但我不太明白C11的措辞.
无论如何,实际问题:这是从C99到C11的变化,还是这些措辞相当?如果是这样,为什么它会被改变?如果没有,有人可以给出一个表达式的例子,这个表达式在C99中是UB而在C11中不是,反之亦然?
当我遇到这个问题时,我正在阅读我的教科书
起初我认为这是未定义的行为,因为a已被多次修改.
那么我就读了这个问题并说它提到了步骤所以我可能认为这个问题是正确的.
所以我的问题是:
注意:一个解释清楚的答案将得到我的投票