热门问题
时间线
聊天
视角

顺序点

来自维基百科,自由的百科全书

Remove ads

顺序点,也称作序列点,是计算机程序中一些执行点,在该点处之前的求值的所有的副作用已经发生,在它之后的求值的所有副作用仍未开始。在CC++程序设计语言中,表达式的值依赖于它的子表达式的求值顺序。增加更多的顺序点限制了可能的求值顺序,能保证有一个一致结果。

C++11中,顺序点概念已经被sequenced before这种方法取代:直接指出一个求值是在另一个求值之前,或者两个求值是无顺序的。[1][2]无顺序的求值可以重叠进行。

歧义例子

考虑两个函数f()g()。在C与C++中,加法运算符+不是一个顺序点,因此表达式f() + g()可能会先调用f(),或先调用g()。逗号运算符引入了一个顺序点,因此表达式f(), g()的求值顺序是确定的:首先调用f(),然后调用g()

当一个变量在一个表达式修改不止一次,顺序点也发挥作用。一个典型的C语言例子是表达式i = i++,其中i的结果值是有二义性的,依赖于表达式求值顺序:自增运算可能发生在赋值之前、之后或者交错进行。在C与C++语言中,这会导致未定义行为。[3]

C与C++的顺序点

在C[4]与C++[5]中,顺序点出现在下述位置:(C++的重载操作符的行为类似于函数)

  1. &&逻辑与)、||逻辑或)、逗号运算符的左操作数与右操作数求值之间(前两者是短路求值的一部分)。例如,表达式*p++ != 0 && *q++ != 0,子表达式*p++ != 0的副作用都会在试图访问q之前完成。
  2. 三元条件运算符的第一个操作数之后,第二或第三操作数之前。例如,表达式a = (*p++) ? (*p++) : 0在第一个*p++之后存在顺序点,因而在第二个*p++求值之前已经做完一次自增。
  3. 完整表达式结束处。包括表达式语句(如赋值a = b;),返回语句ifswitchwhiledo-while语句的控制表达式,for语句的3个表达式。
  4. 函数调用时的函数入口点。函数实参的求值顺序未指定,但顺序点意味着这些实参求值的副作用在进入函数时都已经完成。表达式f(i++) + g(j++) + h(k++),调用f(), g(), h()的顺序未指定,i, j, k的自增顺序也未指定。函数调用f(a,b,c)的实参列表不是逗号运算符,a, b, c的求值顺序未指定。
  5. 函数返回时,在返回值已经复制到调用上下文。(仅C++标准指出这一顺序点[6])
  6. 初始化的结束。例如,声明int a = 5;中的对5求值之后。
  7. 初始化列表的以逗号分割的各个初始化值,严格遵照从左至右求值。例如:int a[3] = {i++,j--,foo(101)};注意,此处不是逗号运算符。(从C++11标准指出这一顺序点)
  8. 在声明序列的每个声明(declarator)之间。例如,int x = a++, y = a++的两次a++求值之间。[7]注意,此例不是逗号运算符。
Remove ads

参考文献

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads