C語言 side effect 和 sequence point

C 語言中,術語副作用(side effect)是指對數據對象或者文件的修改。例如,以下語句        var = 99;
的副作用是把 var 的值修改成 99。對表達式求值也可能產生副作用,例如:
        se = 100
對這個表達式求值所產生的副作用就是 se 的值被修改成 100。
    序列點(sequence point)是指程序運行中的一個特殊的時間點,在該點之前的所有副作用已經結束,並且後續的副作用還沒發生。
    C 語句結束標誌——分號(;)是序列點。也就是說,C 語句中由賦值、自增或者自減等引起的副作用在分號之前必須結束。我們以後會說到一些包含序列點的運算符。任何完整表達式(full expression)運算結束的那個時間點也是序列點。所謂完整表達式,就是說這個表達式不是子表達式。而所謂的子表達式,則是指表達式中的表達式。例如:
        f = ++e % 3
這整個表達式就是一個完整表達式。這個表達式中的 ++e、3 和 ++e % 3 都是它的子表達式。
    有了序列點的概念,我們下面來分析一下一個很常見的錯誤:
        int x = 1, y;
        y = x++ + x++;
這裏 y = x++ + x++ 是完整表達式,而 x++ 是它的子表達式。這個完整表達式運算結束的那一點是一個序列點,int x = 1, y; 中的 ; 也是一個序列點。也就是說,x++ + x++ 位於兩個序列點之間。標準規定,在兩個序列點之間,一個對象所保存的值最多隻能被修改一次。但是我們清楚可以看到,上面這個例子中,x 的值在兩個序列點之間被修改了兩次。這顯然是錯誤的!這段代碼在不同的編譯器上編譯可能會導致 y 的值有所不同。比較常見的結果是 y 的值最後被修改爲 2 或者 3。在此,我不打算就這個問題作更深入的分析,各位只要記住這是錯誤的,別這麼用就可以了。有興趣的話,可以看看以下列出的相關資料。
C 語言標準對副作用和序列點的定義如下:
    Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression may produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.
翻譯如下:
    訪問易變對象,修改對象或文件,或者調用包含這些操作的函數都是副作用,它們都會改變執行環境的狀態。計算表達式也會引起副作用。執行序列中某些特定的點被稱爲序列點。在序列點上,該點之前所有運算的副作用都應該結束,並且後繼運算的副作用還沒發生。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章