C 語言中反作用(side effect):是指對數據對象或者文件的修改。例如,語句 var = 99; 的反作用是把 var 的值修改爲 99。對錶達式求值也可能產生反作用,例如,對錶達式求se = 100;express
求值所產生的反作用就是 se 的值被修改爲 100。ide
序列點(sequence point):是指程序運行中的一個特殊的時間點,在該點以前的全部反作用已經結束,而且後續的反作用還沒發生。C 語句結束標誌——分號(;)是序列點。標準規定,在兩個序列點之間,一個對象所保存的值最多隻能被修改一次。函數
C 語句中由賦值、自增或者自減等引發的反作用在分號以前必須結束。咱們之後會說到一些包含序列點的運算符。任何完整表達式(full expression)運算結束的那個時間點也是序列點。所謂完整表達式,就是說這個表達式不是子表達式。而所謂的子表達式,則是指表達式中的表達式。例如:f = ++e % 3 這整個表達式就是一個完整表達式。這個表達式中的 ++e、3 和 ++e % 3 都是它的子表達式。lua
有了序列點的概念,咱們下面來分析一下一個很常見的錯誤:spa
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.
翻譯以下:code
訪問易變對象,修改對象或文件,或者調用包含這些操做的函數都是反作用,它們都會改變執行環境的狀態。計算表達式也會引發反作用。執行序列中某些特定的點被稱爲序列點。在序列點上,該點以前全部運算的反作用都應該結束,而且後繼運算的反作用還沒發生。對象
順序點有:ci
1. The point of calling a function, after evaluating its arguments.
2. The end of the first operand of the && operator.
3. The end of the first operand of the || operator.
4. The end of the first operand of the ?: conditional operator.
5. The end of the each operand of the comma operator.
6. Completing the evaluation of a full expression. They are the following:
7. Evaluating the initializer of an auto object.
8. The expression in an ‘ordinary’ statement—an expression followed by semicolon.
9. The controlling expressions in do , while , if , switch or for statements.
10. The other two expressions in a for statement.
11. The expression in a return statement.編譯器
編譯時能夠加上「-Wsequence-point 」讓編譯器幫咱們檢查可能的關於檢查點的錯誤。
* test_sequence_point.c * gcc -Wsequence-point test_sequence_point.c */ #i nclude int main() { int i = 12; i = i--; printf("the i is %d/n", i); return 0; }
gcc -Wsequence-point test_sequence_point.c test_sequence_point.c: In function `main': test_sequence_point.c:10: warning: operation on `i' may be undefined