<dfn id="w48us"></dfn><ul id="w48us"></ul>
  • <ul id="w48us"></ul>
  • <del id="w48us"></del>
    <ul id="w48us"></ul>
  • 筆試實例:"序列點" 是什么

    時間:2023-04-04 18:38:12 筆試題目 我要投稿
    • 相關推薦

    筆試實例:"序列點" 是什么

      序列點是一個時間點(在整個表達式全部計算完畢之后或在||、&&、? : 或逗號運算符處, 或在函數調用之前), 此刻塵埃落定, 所有的副作用都已確保結束。ANSI/ISO C 標準這樣描述:在上一個和下一個序列點之間, 一個對象所保存的值至多只能被表

    筆試實例:"序列點" 是什么

      達式的計算修改一次。而且前一個值只能用于決定將要保存的值。第二句話比較費解。它說在一個表達式中如果某個對象需要寫入, 則在同一表達式中對該對象的訪問應該只局限于直接用于計算將要寫入的值。這條規則有效地限制了只有能確保在修改之前才訪問變量的表達式為合法。例如i = i+1 合法, 而a[i] = i++ 則非法

      拓展:

      int i = 3;

      i = i++;

      cout << i;

      結果是什么?有人可能會說是3,也有人可能會說是4,更多的人在罵出題的人白癡,但這語句究竟有何問題呢?未必每個人都清楚。

      有些人也許馬上會說,這是“未定義行為”。沒錯,這是一個典型的未定義行為。i = i++這個表達式合乎C++語法,能夠順利編譯通過,但是執行的結果,標準說“未定義”。為什么是“未定義”,深究起來,要從序列點說起。

      序列點是程序中這樣的一些點:通俗地說,執行至此,之前的語句都已經徹底執行干凈執行完了,之后的語句還完全沒開始執行;更常見、更嚴謹但略晦澀的說法是,之前的語句對現場環境的改變已經全部完成,之后的語句對現場環境的改變還沒有開始。啥是現場環境呢?就是程序執行到某一點的那個狀態,包括變量的內容、文件的內容等。

      這跟最開始那個例子有什么關系呢?關鍵的問題來了:標準規定,兩個序列點之間,程序執行的順序可以是任意的。沒錯,正如你猜的那樣,C++標準規定一個完整的表達式結束之后有一個序列點,而例子中i = i++是位于兩個序列點之間的。編譯器可以先算完i++,再寫結果給i,也可以先將i = i,再令i++。按前面的方法算,i先自增變為4,然后i++返回3,于是i被賦值為3;按后一種方法算,i先被賦值為3,隨后自增變成4。標準說了,這兩種處理方法,編譯器你愛選那種就選哪種,隨便。如果誰寫的程序像這樣依賴執行的順序,讓他自己哭去!

      等等,有人要問了,++的優先級難倒不是高于=嗎?顯然應該先執行++啊。這里有個概念的問題,前一段說的編譯器先算i = i,絕不是說令=的優先級比++還高了。如果那樣的話,表達式將變成 (i = i)++,也就是i.operator = (i). operator ++,執行++的主體變成i = i這個表達式的返回值了。上一段所說的先計算i = i,實際上還是先計算i++,只不過是先返回了i的值,然后推遲了將i自增1的操作先去干別的(i = i)去了,回頭再來給i自增1。

      ——“什么,你說先干別的就先干別的,憑什么!”

      嗯,我再重復一遍,標準規定,兩個序列點之間,程序執行的順序可以是任意的。

      ——“不是吃飽了撐的嘛,標準搞這個干啥?嚴格按照順序執行不就完了嘛”。

      C++標準弄這么復雜自然是有道理的。C++是極為重視執行效率的語言,這樣做給了編譯器優化的空間。比如考慮

      int j = i++;

      如果非得把i++執行干凈了再干別的,那就不得不 temp = i; i += 1; j = i; 。如果允許編譯器打亂順序執行呢,直接 j = i; i +=1; 就好了,省了一個temp倒一次的過程。

      多說一句,一些更高層的語言,不是像C++這種極為重視效率的,比如Java,上面的例子就完全沒有問題。Java完全不允許你編譯器亂搞,上面那個例子,在Java中一定是先把i++徹底執行干凈了返回3,再進行賦值,賦值完之后不會再有別的操作了,所以結果一定是3。

      如何避免由序列點造成的這種未定義行為,有一句經典但有點晦澀的編程規則:“在相鄰的兩個序列點之間,一個對象只允許被修改一次,而且如果一個對象被修改則在這兩個序列點之間只能為了確定該對象的新值而讀一次”。其實明白了序列點具體是怎么回事,這個規則應該就很容易明白了。由于序列點之間程序執行順序不確定,一個對象被修改多次的話最后留下的是哪次的結果就不確定。另外如果一個對象同時存在讀取和修改,只有根據讀取的結果來修改才是合法的,否則就會出現是先改完再讀還是先讀完再改的混亂。

      最后再說一下最新的C++2003標準中定義的序列點(詳細說明請參考標準):

      ·完整聲明之后

      ·完整表達式之后

      ·進入函數時與退出函數時

      ·|| && ?: , 四個操作符的第一個操作數之后

      最后一個似乎有點奇怪,為啥 + - 操作符之前就沒有序列點,|| &&之前就有呢?a+b之間沒有序列點而a||b之間就有,不公平啊。

      嗯,你猜的沒錯,是為了短路。

      不過要是手賤重載了默認的||和&&,他們可就視同普通函數,不會在第一個操作數之后有序列點了,切記。

    【筆試實例:"序列點" 是什么】相關文章:

    求職筆試常見試題分類及實例解析02-16

    求職筆試常見試題分類及實例解析08-11

    m序列與gold序列性能分析比較03-07

    筆試的特點是什么11-08

    基于時間序列理論方法的生物序列特征分析11-20

    瑪氏筆試的一點體會11-21

    南京 宣講會+筆試 一點點感想08-10

    安永香港今年筆試內容是什么?11-21

    做完online筆試,大家的申請界面是什么?11-21

    北京畢馬威筆試時間是什么時候?08-10

    主站蜘蛛池模板: 亚洲AV无码久久精品色欲| 无码少妇精品一区二区免费动态 | 久久亚洲欧美日本精品| 亚洲一区二区三区国产精品| 亚洲永久永久永久永久永久精品| 日韩精品一区二区三区中文| 国产精品婷婷午夜在线观看| 久久91精品国产91久久户| 亚洲国产另类久久久精品| 91po国产在线精品免费观看| 精品一区二区三区在线成人| 久久国产美女免费观看精品| 成人精品视频在线观看| 亚洲人成电影网站国产精品| 国产精品自在在线午夜福利| 国产精品久久久久天天影视| 乱精品一区字幕二区| 亚洲精品人成无码中文毛片| 国产精品H片在线播放| 高清免费久久午夜精品| 亚洲AV无码精品色午夜果冻不卡| 国产精品最新国产精品第十页 | 国产成人精品无码一区二区| 国产精品免费αv视频| 国产精品亚洲A∨天堂不卡| 亚洲精品麻豆av| 久久久无码精品午夜| 无翼乌无遮挡全彩老师挤奶爱爱帝国综合社区精品 | 国产A级毛片久久久精品毛片| 精品无码日韩一区二区三区不卡 | 久久精品这里只有精99品| 亚洲欧美日韩精品| 国产精品视频一区国模私拍| 欧美午夜精品久久久久久浪潮| 亚洲第一极品精品无码久久| 久久se精品一区二区影院| 四虎精品成人免费观看| 成人区人妻精品一区二区不卡视频| 国产精品视频一区二区三区经| 在线成人精品国产区免费| 无翼乌无遮挡全彩老师挤奶爱爱帝国综合社区精品 |