什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
术语"运算符优先级"和"评估顺序"是编程中非常常用的术语,对于程序员来说非常重要.而且,据我所知,这两个概念紧密相连; 在谈论表达时,一个人离不开另一个人.
我们举一个简单的例子:
int a=1; // Line 1
a = a++ + ++a; // Line 2
printf("%d",a); // Line 3
Run Code Online (Sandbox Code Playgroud)
现在,很明显会Line 2导致未定义的行为,因为C和C++中的序列点包括:
在评估&&(逻辑AND)的左右操作数之间,|| (逻辑OR)和逗号运算符.例如,在表达式中
*p++ != 0 && *q++ != 0,子表达式的所有副作用*p++ != 0都在任何访问尝试之前完成q.在评估三元"问号"运算符的第一个操作数和第二个或第三个操作数之间.例如,在表达式中,在第
a = (*p++) ? (*p++) : 0一个之后存在一个序列点*p++,这意味着它已经在第二个实例执行时增加了.在完整表达结束时.此类别包括表达式语句(例如赋值
a=b;),return语句,if,switch,while或do-while语句的控制表达式,以及for语句中的所有三个表达式.在函数调用中输入函数之前.未指定参数的计算顺序,但此序列点表示在输入函数之前所有副作用都已完成.在表达式中
f(i++) + g(j++) + h(k++),f使用原始值的参数调用i,但i在进入正文之前递增f.同样,j和k正在进入前更新g和h分别.然而,不指定以何种顺序f() …
在C/C++的每本教科书中,您都可以找到运算符优先级和关联表,如下所示:

http://en.cppreference.com/w/cpp/language/operator_precedence
StackOverflow上的一个问题是这样的:
以下函数的执行顺序如下:
f1() * f2() + f3();
f1() + f2() * f3();
参考上面的图表,我自信地回答说函数具有从左到右的关联性,因此在前面的语句中,在这两种情况下都会像这样评估:
f1() - > f2() - > f3()
评估函数后,您完成评估,如下所示:
(a1*a2)+ a3
a1 +(a2*a3)
令我惊讶的是,很多人告诉我,我错了.决心证明他们错了,我决定转向ANSI C11标准.我再一次惊讶地发现在运算符优先级和关联性方面提到的很少.
我正在学习C,因此尝试了以下代码,并获得了7,6而不是的输出6,7。为什么?
#include <stdio.h>
int f1(int);
void main()
{
int b = 5;
printf("%d,%d", f1(b), f1(b));
}
int f1(int b)
{
static int n = 5;
n++;
return n;
}
Run Code Online (Sandbox Code Playgroud)