?
このドキュメントでは、 php中國語ネットマニュアル リリース
(包括函數(shù)調(diào)用表達(dá)式中函數(shù)參數(shù)的評估順序,以及任何表達(dá)式中子表達(dá)式的評估順序)的任何C運(yùn)算符的操作數(shù)的評估順序是未指定的(除非在下面指出)。編譯器將以任何順序?qū)λ鼈冞M(jìn)行評估,并且可以在再次評估同一個表達(dá)式時選擇另一個順序。
在C中沒有從左到右或從右到左的評估概念,這不應(yīng)該與操作符的從左到右和從右到左的關(guān)聯(lián)性相混淆:表達(dá)式f1() + f2() + f3()
被解析為(f1() + f2()) + f3()
由于左operator +的從右到關(guān)聯(lián)性,但函數(shù)調(diào)用f3
可以在運(yùn)行時首先,最后或之間f1()
或f2()
在運(yùn)行時進(jìn)行評估。
編譯器對每個表達(dá)式或子表達(dá)式執(zhí)行兩種評估(兩者都是可選的):
值計算:計算表達(dá)式返回的值。這可能涉及確定對象的身份(左值評估)或讀取先前分配給對象的值(右值評估)
副作用:訪問(讀取或?qū)懭耄┯梢鬃兊淖笾抵付ǖ膶ο?,修改(寫入)對象,原子同步(自C11起),修改文件,修改浮點(diǎn)環(huán)境(如果支持)或調(diào)用一個執(zhí)行任何這些操作的函數(shù)。
如果表達(dá)式不產(chǎn)生副作用,并且編譯器可以確定該值未被使用,則表達(dá)式可能不會被評估。
“sequenced-before”是同一線程內(nèi)的評估之間的不對稱,傳遞,成對關(guān)系(如果涉及原子類型和內(nèi)存障礙,它可以跨線程延伸)。
如果一個序列點(diǎn)存在于子表達(dá)式E1和E2之間,那么E1的值計算和副作用都被排序 - 在 E2的每個值計算和副作用之前
如果在評估B之前對評估A進(jìn)行排序,那么在開始評估B之前評估A將會完成。如果A在B之前未被測序,而B在A之前被測序,那么在評估A開始之前B的評估將完成。如果A不B之前測序和B不是A之前測序,然后兩種可能性存在:A,B的評價是未測序:它們可以以任何順序執(zhí)行,并且可以重疊(單個執(zhí)行線程內(nèi),編譯器可以交織包含A和B)的A和B評估的CPU指令是不確定地排序的:它們可以以任何順序執(zhí)行但可能不重疊:A在B之前將是完整的,或者B將在A之前完成。在下一次評估同一個表達(dá)式時是相反的。 | (自C11以來) |
---|
如果在評估B之前對評估A進(jìn)行排序,那么在開始評估B之前評估A將會完成。
如果A在B之前未被測序,而B在A之前被測序,那么在評估A開始之前B的評估將完成。
如果A在B和B未在A之前排序之前未被測序,則存在兩種可能性:
A和B的評估是不確定的:它們可以以任何順序執(zhí)行并且可以重疊(在單個執(zhí)行線程內(nèi),編譯器可以交織包括A和B的CPU指令)
A和B的評估是不確定地排序的:它們可以以任何順序執(zhí)行但可能不重疊:A會在B之前完成,或B在A之前完成。順序可能與下次相同表達(dá)式相反被評估。
(since C11)
1)評估所有函數(shù)參數(shù)和函數(shù)指示符后,以及實(shí)際函數(shù)調(diào)用之前,有一個序列點(diǎn)。
2)在評估第一個(左)操作數(shù)之后以及評估以下二元運(yùn)算符的第二個(右)操作數(shù)之前,有一個序列點(diǎn):( &&
邏輯AND),||
(邏輯OR)和,
(逗號)。
3)在評估第一個(左)操作數(shù)之后并且在評估第二個或第三個操作數(shù)(以評估者為準(zhǔn))之前有一個序列點(diǎn), ?:
4)在完整表達(dá)式(表達(dá)式不是子表達(dá)式:通常是以分號或if / switch / while / do的控制語句結(jié)束的表達(dá)式)和下一個完整表達(dá)式之前有一個序列點(diǎn)。
5)完整聲明的結(jié)尾處有一個序列點(diǎn)。6)在函數(shù)返回之前有一個序列點(diǎn)。7)在格式化I / O中的每個轉(zhuǎn)換說明符相關(guān)的動作之后有一個序列點(diǎn)(特別是,對于scanf將不同的字段寫入同一變量以及用于讀取和修改或修改相同變量的printf變量不止一次使用%n)8)在每次調(diào)用庫函數(shù)qsort和bsearch所做的比較函數(shù)之前以及之后,以及任何對比較函數(shù)的調(diào)用和關(guān)聯(lián)對象的移動之間都有序列點(diǎn)由qsort制作 | (自C99以來) |
---|---|
9)操作數(shù)對任何操作符的值計算(但不是副作用)在操作符結(jié)果的值計算之前(但不包括其副作用)排序。10)直接賦值運(yùn)算符和所有復(fù)合賦值運(yùn)算符的副作用(左變元的修改)在左和右兩個參數(shù)的值計算(但不是副作用)之后排序。11)后增量和后減算子的值計算在其副作用之前被排序。12)在另一個函數(shù)調(diào)用之前或之后未被排序的函數(shù)調(diào)用被不確定地排序(構(gòu)成不同函數(shù)調(diào)用的CPU指令不能交錯,即使函數(shù)被內(nèi)聯(lián))13)在初始化列表表達(dá)式中, | (自C11以來) |
1)如果對標(biāo)量對象的副作用相對于同一標(biāo)量對象上的另一副作用而言是不確定的,則行為是不確定的。
i = ++i + i++; // undefined behaviori = i++ + 1; // undefined behaviorf(++i, ++i); // undefined behaviorf(i = -1, i = -1); // undefined behavior
2)如果標(biāo)量對象的副作用相對于使用相同標(biāo)量對象的值進(jìn)行值計算而言是未定序的,則行為是未定義的。
f(i, i++); // undefined behaviora[i] = i++; // undefined bevahior
3)只要子表達(dá)式的至少一個允許排序允許這樣一個不確定的副作用,上述規(guī)則就適用。