順序點,也稱作序列點,是電腦程式中一些執行點,在該點處之前的求值的所有的副作用已經發生,在它之後的求值的所有副作用仍未開始。在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]注意,此例不是逗號運算子。

參考文獻

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.