什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式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
我很好奇初始化列表和序列点.我刚才读到初始化程序列表中的评估顺序是从左到右.如果是这样,那么评估点之间肯定会有某种序列点,我错了吗?那么说是以下有效代码?是否有任何导致其未定义的行为?
int i = 0;
struct S {
S(...) {}
operator int() { return i; }
};
int main() {
i = S{++i, ++i};
}
Run Code Online (Sandbox Code Playgroud)
任何和所有回复都表示赞赏.
考虑以下代码:
int main()
{
int count = 0 ;
int arrInt[2] = { count++, count++ } ;
return 0 ;
}
Run Code Online (Sandbox Code Playgroud)
如果我们使用clang -std=c++03它编译代码,则会产生以下警告(实时示例):
warning: multiple unsequenced modifications to 'count' [-Wunsequenced]
int arrInt[2] = { count++, count++ } ;
^ ~~
Run Code Online (Sandbox Code Playgroud)
我不是在提倡这样的代码,但是在另一个问题中出现了类似的代码,并且对于是否根据标准C ++ 11进行定义存在分歧。在C ++ 11中,根据初始化程序中的多个突变是否列出未定义的行为,此行为是定义良好的行为,并且如果我使用该警告,则该警告消失了。-std=c++11
如果我们看一下C ++ 11 之前的标准草案,它没有覆盖initializer-list的相同语言,那么似乎我们剩下的是Chapter 5 Expressions第4段:
除非另有说明,否则未指定各个运算符的操作数和各个表达式的子表达式的求值顺序以及发生副作用的顺序。57)在上一个序列点与下一个序列点之间,标量对象最多应通过表达式的计算修改其存储值。此外,应仅访问先验值以确定要存储的值。对于完整表达式的子表达式的每个允许的排序,都应满足本段的要求;否则,行为是不确定的。
为了使这个未定义,我们似乎必须将其解释count++, count++ …