最近在讀order of evaluation violations,其中的一個例子使我很困惑。 1)如果對一個標量對象的副作用相對於對這個標量對象的另一個副作用是無序的,那麼這是未定義行為。 在這段代碼中,很明顯 i 是一個標量對象。 算術類型(3.9.1),枚舉類型,指針類型,指針成員類型(3. ...
最近在讀order of evaluation violations,其中的一個例子使我很困惑。
1)如果對一個標量對象的副作用相對於對這個標量對象的另一個副作用是無序的,那麼這是未定義行為。
//代碼片段 f(i=-1,i=-1);//undefined behavior 未定義行為
在這段代碼中,很明顯 i 是一個標量對象。
算術類型(3.9.1),枚舉類型,指針類型,指針成員類型(3.9.2),空指針類型和被const或volatile修飾的類型(3.9.3)等統稱為標量類型。
從這句話中我看不出上面那句代碼有什麼分歧的地方。我認為不論第一個參數還是第二個參數先執行,i最終都是-1,並且兩個參數的值都是-1。
有人能解釋清楚這些嗎?
最佳答案:
既然運算是無序的,也就不能說分配任務的指令不能交錯執行。也許會選擇最佳的方式去運行,由CPU的架構來決定。引用下麵這句話來說明:
如果A在B之前是無序的並且B在A之前是無序的,那麼存在兩種可能性:
(1)預估A和B是無序的:它們可能以任意的順序運行並且可能會重疊(在一個線程的執行中,編譯器可能會交錯組織包含A和B的CPU指令)。
(2)預估A和B是無法確定的順序:它們可能以任意順序運行但是一定不會重疊。或者A在B執行之前完成或者B在A執行之前完成。下一次執行同樣的語句時,執行的順序有可能是相反的。
假設運算執行後,把-1存進一個記憶體地址,就這個行為自身而言,這似乎並不會引發任何問題。但是如果一個指令和另一個指令交錯執行操作同一個記憶體地址,你不能說編譯器不會把這些指令優化成一個獨立的具有同樣效果的指令集,這樣就會出錯了。
例如,假想把記憶體清零然後再遞減是最高效的。現在開始值是-1,然後就是:
f(i=-1,i=-1)
也許會變成:
clear i //清空 i clear i //清空 i decr i //遞減 i decr i //遞減 i
現在i是-2。
這也許是一個假的例子,但可能是真的。
博主是一個有著7年工作經驗的架構師,對於c++,自己有做資料的整合,一個完整學習C語言c++的路線,學習資料和工具。可以進我的Q群7418,18652領取,免費送給大家。希望你也能憑自己的努力,成為下一個優秀的程式員!另外博主的微信公眾號是:C語言編程學習基地,歡迎關註!