术语"运算符优先级"和"评估顺序"是编程中非常常用的术语,对于程序员来说非常重要.而且,据我所知,这两个概念紧密相连; 在谈论表达时,一个人离不开另一个人.
我们举一个简单的例子:
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() …
为什么先++x || ++y && ++z
计算++x
,即使运算符的优先级&&
高于||
?
如果你看一下C的优先级表,你会发现&&的优先级高于||.
但是看看下面的代码:
a=b=c=1;
++a || ++b && ++c;
printf("%d %d %d\n",a,b,c);
Run Code Online (Sandbox Code Playgroud)
它打印出"2 1 1",这意味着首先评估"++ a",一旦程序看到TRUE,它就会停在那里,因为在||的另一边是什么 并不重要.
但由于&&的优先级高于||,因此不应首先评估"++ b && ++ c",然后将结果插回"++ a || result"?(在这种情况下,程序将打印"1 2 2").