簡體   English   中英

C中的序列點和副作用

[英]Sequence points and side effects in C

在這個C-FAQ中給出了序列點 ;

標准規定:
在前一個和下一個序列點之間,對象的存儲值最多只能通過表達式的計算修改一次。 此外,只能訪問先前值以確定要存儲的值。

在例子中

i = i++;
a[i] = i++;

從聲明的第一句可以清楚地看出,這些例子是未定義行為的結果。
在解釋聲明的第二句時,據說;

第二句話說: 如果一個對象被寫入一個完整的表達式,那么同一個表達式中對它的任何和所有訪問都必須直接參與計算要寫入的值。 此規則有效地將法律表達式約束為在修改之前明顯存在訪問的表達式。 例如,舊備用

 i = i + 1 

是允許的,因為i的訪問用於確定i的最終值。 這個例子

a[i] = i++

是不允許的,因為i的一個訪問(a [i]中的一個)與最終存儲在i中的值無關(在i ++中發生),因此沒有好的方法來定義。

我的問題是;
1.它是什么意思, 如果一個對象被寫入一個完整的表達式,那么在同一個表達式中對它的任何和所有訪問必須直接參與計算要寫入的值。

2.它是什么意思,例子a[i] = i++ 被禁止,因為i的一個訪問(a [i]中的一個)與最終存儲在i中的值無關(其中發生在i ++)
有人可以用一些簡單的方法解釋它嗎?

我的問題是; 1.它是什么意思,如果一個對象被寫入一個完整的表達式,那么在同一個表達式中對它的任何和所有訪問都必須直接參與到要寫入的值的計算中。

使用像i++這樣的子表達式, i被寫入。 而且,賦值是一個表達式,所以在i = 2i被寫入。 a = b是表達式可能不是很明顯,但確實如此。 這就是為什么你可以做一些事情,比如a = b = c ,這是好的, if (a = b)哪個不太好。

那么它是什么要說的是,如果你寫信給i ,用= ,或前或后加,然后我的任何訪問必須是我的新價值計算的一部分。 然而,這很重要,計算前后增量所涉及的唯一事情是在語句開頭的 i的值。

2.它是什么意思,例子a [i] = i ++被禁止,因為i的一個訪問(a [i]中的一個)與最終存儲在i中的值無關(其中發生在i ++)

正是它所說的。 當訪問ia[i]它不是新的值的計算的一部分i導致從i++

有人可以用一些簡單的方法解釋它嗎?

簡單方法:不要在表達式中使用前置或后置增量。 總是在聲明中自己使用它們。 如果你真的必須,請不要在整個語句中的任何其他位置使用相同的變量。

這種解釋很奇怪,我無法理解它。

真正的解釋是表達式i++具有副作用(遞增i ),可以在評估此特定i之后的任何時間應用。

由於在序列點之外,C語言不保證評估順序或應用后遞增的時間(可能出於性能原因),在第二個示例中可能發生三件事(假設在行之前i = 5 ) :

  • 首先評估最左邊的ia[i]中的a[i] ),以計算用於存儲的[i]的地址。 然后評估最右邊的i ,然后應用后增量:該行執行a[5] = 5; i=6; a[5] = 5; i=6;
  • 最右邊的i首先計算,則最左邊的一個,然后i當所有是說,做了-遞增后施加:在這種情況下,效果是相同於上面的情況。
  • 首先評估最右邊的i ,立即應用后增量,然后評估最左邊的i以計算用於存儲的[i]的地址。 這次效果是a[6] = 5; i=6 a[6] = 5; i=6

結果的選擇不僅取決於編譯器的選擇,還取決於編譯器的設置:Microsoft Visual C ++可以根據您是在Debug還是Release中編譯來提供不同的結果。

最后我得到了關於這一點的SO的解釋 看完后常見問題 我得出的結論是;

最后一句話

此外,只能訪問先前值以確定要存儲的值

會是這樣的;

此外,只能訪問對象的先前值以確定要存儲的( 同一對象的修改/新值。

通過這個例子很清楚

 int i = 1, j, a[5];    
 i = i + 1;
 j = i + 1;
 a[i] = i; 

在表達式i = i + 1情況下, i (在RHS中)的先前值(在此為1 )被訪問以確定要存儲的i的值,這就是語句

如果一個對象被寫入一個完整的表達式,那么在同一個表達式中對它的任何和所有訪問都必須直接參與計算要寫入的值。

說。
而在的情況下, j = i + 1a[i] = i ,的訪問值i 只是重視 不是 現有值作為沒有在那里i在這些語句修改。

第二個問題可以解釋為;
在表達式a[i] = i++a[i++] = i ,上述語句的第一句

在前一個和下一個序列點之間,對象的存儲值最多只能通過表達式的計算修改一次。

失敗,因為i 在兩個連續的序列點之間只修改了一次 這就是為什么我們需要第二句話。
這兩個例子是使用C不允許的,因為在現有值i訪問兩次,即, i++本身的訪問之前值 i在表達式對其進行修改和先前值的因而其它接入/ i是不必要,因為它不訪問確定要存儲的修改值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM