2010-11-05 64 views
8

最近,我看到了很多的問題,被問及輸出一些瘋狂但語法允許代碼之類的語句像i = ++i + 1i=(i,i++,i)+1;。坦率地說,實際上很難有人在實際編程中編寫任何這樣的代碼。坦率地說,我從未在我的專業經歷中遇到任何這樣的代碼。所以我通常最終在SO上跳過這樣的問題。但最近Q這種問題的絕對數量讓我想起如果我錯過了某些重要的理論,跳過這樣的Q.我認爲這樣的Q's圍繞着Sequence points。我幾乎不知道任何有關順序點的內容,坦率地說,我只是想知道如果不知道它是否會阻礙某些方面。那麼有人可以解釋Sequence points的理論/概念,或者如果可能的話,指出一個解釋這個概念的資源。另外,是否值得投入時間來了解這個概念/理論?的有關順序的說明指出

+3

史蒂夫峯會的文章[這裏](http://c-faq.com/expr/seqpoints.html)將是有益的。 – 2010-11-05 11:35:13

+3

閱讀第1.9節,以及對第5節的介紹(即5.1之前)。 – 2010-11-05 11:44:06

回答

5

我能想到的最簡單的回答是:

C++是在抽象機的定義。在抽象機器上執行的程序的輸出僅根據執行「副作用」的順序來定義。並且副作用被定義爲對IO庫函數的調用,並且對變量標記爲volatile。

C++編譯器被允許爲所欲爲內部要優化代碼,但不能寫入的順序更改爲volatile變量和IO調用。

序列點定義在C/C++程序的心跳 - 序列點之前的副作用是「完整」和副作用序列點後還沒有發生。但是,副作用(或者代碼,可以實現內副作用間接(序列點可以被重新排序。

這就是爲什麼理解它們是非常重要的。如果沒有這種認識,一個什麼樣的你的基本認識C++程序是(以及它如何可能是由侵略性的編譯器優化)是有缺陷的。

2

http://en.wikipedia.org/wiki/Sequence_point

這是一個很簡單的概念,所以你並不需要投入太多的時間:)

+4

我不同意它是一個簡單的概念,從我在線程和解釋中看到的它似乎是一個相當棘手的概念,或者對我來說似乎很難! – 2010-11-05 10:42:38

+0

看看維基百科的文章。第一句話基本上定義了這個概念。有很多關於C++中序列出現的細節,但這不是關於這個概念的。 – 2010-11-05 10:57:00

1

值得一知道存在該序列點,因爲如果你不知道他們,你可以很容易地編寫代碼,這似乎在測試中運行良好,但實際上未定義,並且在另一臺計算機上運行它或使用不同的編譯選項時可能會失敗。特別地,如果你寫例如x++作爲較大表達也包括x可以很容易地遇到問題的一部分。

我不認爲有必要充分了解所有規則 - 但是您需要知道何時需要檢查規範,或者更好 - 何時重寫代碼以使其不會更新如果更簡單的設計也可以工作,則依賴序列點規則。

+0

我知道這是相當主觀的要求,但知道有多少知識足夠?一個必須/ ATLEAST知道什麼規則? – 2010-11-05 10:38:04

0
int n,n_squared; 
for(n=n_squared=0;n<100;n_squared+=n+ ++n) 
printf("%i squared might or might not be %i\n",n,n_squared); 

...並不總是做你認爲它會做的。這可以使調試痛苦。 原因是++ n檢索,修改和存儲n的值,這可能在檢索n之前或之後,因此n_squared的值在第一次迭代。序列點保證子表達式按順序進行評估。

2

的序列點的精確技術細節可能會很麻煩,是的。但是,以下指南解決幾乎所有的實際問題:

  • 如果表達式修改的值,所以必須修改和任何其他使用該值之間的序列點。
  • 如果你不知道是否值的兩個用途由序列點分離與否,你的代碼分解成多個語句。

這裏 「修飾」 包括關於=+=等左手值分配操作,並且還++xx++--x,和x--語法。 (它通常是這些遞增/遞減表現,其中一些人試圖聰明,並最終陷入麻煩。)

幸運的是,在大多數的「預期」的地方有順序點:

  • 在每一份聲明或聲明的結尾。
  • 在每個函數調用的開始和結束處。
  • 在內置&&||運營商。
  • 在在三元表達?
  • 在內置,逗號操作。 (最常見的爲條件,如for (a=0, b=0; a<m && b<n; ++a, ++b)。)分隔函數參數逗號是逗號運算符和是的序列點。

重載operator&&operator||operator,不會引起序列點。從這個事實中可能產生的驚喜是超載他們的一個原因通常是不鼓勵的。