[英]Evaluation Order of C Language
x+=x*=x
是未定義的行為嗎?14) 對於不確定順序的 function 調用,復合賦值運算符的操作,以及遞增和遞減運算符的前綴和后綴 forms 都是單次評估。
x+=x*=x
具有未定義的行為,因為x
在序列點之間被分配了兩次。
C11、C17中14)對應的文字說
形式為 E1 op= E2 的復合賦值等價於簡單賦值表達式 E1 = E1 op (E2),除了左值 E1 僅計算一次,並且對於不確定順序的 function 調用,a 的操作復合賦值是一個單一的評估。
我相信這意味着
int x = 0;
int foo(void) {
x = 5;
return x;
}
int main(void) {
int y = foo() + (x += 2);
}
將具有以下任一行為
int main(void) {
int _tmp = x += 2;
int y = foo() + _tmp;
}
或者
int main(void) {
int _tmp = foo();
int y = _tmp + (x += 2);
}
並且不能拆分為例如
int main(void) {
int _tmp = x;
int _tmp2 = foo();
x = _tmp + 2;
int y = _tmp2 + x;
}
注意這個保證是C11中新增的,在C89、C99中是不存在的。
1) 是的。
C17 6.5.16 賦值運算符,§3
操作數的評估是無序的。
由於 C17 6.5 §2,這使它成為 UB
如果標量 object 上的副作用相對於同一標量 object 上的不同副作用或使用相同標量 ZA8CFDE6331BD59EB2AC96F8911C4B66Z 的值的值計算未排序,則行為未定義
每個任務都是一個副作用。 C99 有相同的規則,但更容易理解:
C99 6.5 §2
在前一個和下一個序列點之間,object 的存儲值最多只能通過表達式的評估修改一次。 此外,應僅讀取先驗值以確定要存儲的值。
2) 所有帶有 C11 序列變化的文本閱讀起來相當混亂。 他們使用沒有在任何地方正式定義的術語,例如“單一評估”。
規范性文本為 C17 6.5.15.2 §3
形式為 E1 op= E2 的復合賦值等價於簡單賦值表達式 E1 = E1 op (E2),除了左值 E1 僅計算一次,並且對於不確定順序的 function 調用,a 的操作復合賦值是一個單一的評估。
我想這只是意味着像int x;
這樣的操作。 ... x += 1
應該產生如下機器代碼:
否則,假設某些東西在更新x
的操作之間獲得序列。 但是復合賦值無論如何都不是原子的,所以我不太明白這里的標准是什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.