热门问题
时间线
聊天
视角

順序點

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

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