4 回答

TA貢獻(xiàn)1900條經(jīng)驗(yàn) 獲得超5個(gè)贊
register
編輯:
如果lvalue指定可以用寄存器存儲(chǔ)類(lèi)聲明的具有自動(dòng)存儲(chǔ)持續(xù)時(shí)間的對(duì)象(從未使用其地址),且該對(duì)象未初始化(未使用初始化器聲明,且未在使用前對(duì)其執(zhí)行賦值),則行為未定義。
unsigned char a, b;memcpy(&a, &b, 1);a -= a;
這里的地址 a
和 b
所以它們的價(jià)值是不確定的。 自 unsigned char
從未有不確定值只是未指定的陷阱表示,任何 unsigned char
可能會(huì)發(fā)生。 最后 a
必持有價(jià)值 0
.
編輯2: a
b
3.19.3 未指定值
在本國(guó)際標(biāo)準(zhǔn)不要求在任何情況下選擇值的相關(guān)類(lèi)型的有效值

TA貢獻(xiàn)1830條經(jīng)驗(yàn) 獲得超9個(gè)贊
C標(biāo)準(zhǔn)為編譯器提供了很大的空間來(lái)執(zhí)行優(yōu)化。如果假設(shè)程序的天真模型將未初始化的內(nèi)存設(shè)置為一些隨機(jī)位模式,并且所有操作都按照編寫(xiě)的順序執(zhí)行,那么這些優(yōu)化的結(jié)果可能會(huì)令人驚訝。
注意:以下示例僅有效,因?yàn)?code>x它的地址從來(lái)沒(méi)有被占用過(guò),所以它是“注冊(cè)式的”。如果x
有陷阱表示;這種情況很少發(fā)生在無(wú)符號(hào)類(lèi)型(它至少需要“浪費(fèi)”一點(diǎn)存儲(chǔ)空間,并且必須有文檔記錄),而且不可能用于unsigned char
。如果x
如果有符號(hào)類(lèi)型,則實(shí)現(xiàn)可以定義在-(2)之間不是數(shù)字的位模式。恩-1-1)和2恩-1-1作為陷阱代表。
編譯器試圖將寄存器分配給變量,因?yàn)榧拇嫫鞅葍?nèi)存更快。由于程序可能使用比處理器擁有寄存器更多的變量,編譯器執(zhí)行寄存器分配,從而導(dǎo)致在不同時(shí)間使用相同寄存器的不同變量??紤]程序片段
unsigned?x,?y,?z;???/*?0?*/y?=?0;??????????????/*?1?*/z?=?4;??????????????/*?2?*/x?=?-?x;????????????/*?3?*/y?=?y?+?z;? ?????????/*?4?*/x?=?y?+?1;??????????/*?5?*/
當(dāng)計(jì)算第3行時(shí),x
還沒(méi)有初始化,因此(編譯器的原因)第3行必須是某種僥幸,這是由于編譯器不夠聰明而無(wú)法解決的其他情況。自z
不在第4行之后使用,并且x
如果不在第5行之前使用,則可以對(duì)兩個(gè)變量使用相同的寄存器。因此,這個(gè)小程序被編譯成寄存器上的以下操作:
r1?=?0;r0?=?4;r0?=?-?r0;r1?+=?r0;r0?=?r1;
的最終價(jià)值x
的最終值r0
的最終價(jià)值y
的最終值r1
。這些值是x=-3和y=-4,而不是如果x
已經(jīng)正確初始化了。
關(guān)于更詳細(xì)的示例,請(qǐng)考慮以下代碼片段:
unsigned?i,?x;for?(i?=?0;?i?<?10;?i++)?{ ????x?=?(condition()???some_value()?:?-x);}
假設(shè)編譯器檢測(cè)到condition
沒(méi)有副作用。自condition
不修改x
,編譯器知道循環(huán)中的第一次運(yùn)行不可能訪問(wèn)x
因?yàn)樗€沒(méi)有初始化。因此,循環(huán)體的第一次執(zhí)行相當(dāng)于x = some_value()
沒(méi)有必要測(cè)試條件。編譯器可能會(huì)編譯這段代碼,就好像您已經(jīng)編寫(xiě)了
unsigned?i,?x;i?=?0;?/*?if?some_value()?uses?i?*/x?=?some_value();for?(i?=?1;?i?<?10;?i++)?{ ????x?=?(condition()???some_value()?:?-x);}
在編譯器中建模的方式是考慮任何依賴(lài)于x
有無(wú)論什么價(jià)值都是方便的只要x
未初始化。由于未初始化變量的行為是未定義的,而不是僅具有未指定值的變量,所以編譯器不需要跟蹤任何方便的值之間的任何特殊的數(shù)學(xué)關(guān)系。因此,編譯器可以這樣分析上面的代碼:
- 在第一次循環(huán)迭代中,
未初始化的x
被評(píng)估。-x
有未定義的行為,所以它的價(jià)值是什么-是方便。-x
- 優(yōu)化規(guī)則
應(yīng)用,以便將此代碼簡(jiǎn)化為condition ? value : value
condition; value
.
當(dāng)遇到問(wèn)題中的代碼時(shí),這個(gè)編譯器會(huì)在x = - x
的值。-x
什么都方便。這樣就可以優(yōu)化分配。
我還沒(méi)有尋找像上面所描述的編譯器的例子,但是這是好的編譯器嘗試做的優(yōu)化的類(lèi)型。我不會(huì)驚訝地遇到一個(gè)。下面是一個(gè)你的程序崩潰的編譯器的不太合理的例子。(如果您在某種高級(jí)調(diào)試模式下編譯您的程序,可能就不會(huì)那么難以置信了。)
此假設(shè)編譯器映射不同內(nèi)存頁(yè)中的每個(gè)變量,并設(shè)置頁(yè)屬性,以便讀取未初始化的變量會(huì)導(dǎo)致調(diào)用調(diào)試器的處理器陷阱。對(duì)變量的任何賦值首先要確保其內(nèi)存頁(yè)被正常映射。此編譯器不嘗試執(zhí)行任何高級(jí)優(yōu)化-它處于調(diào)試模式,目的是很容易地定位bug,如未初始化的變量。什么時(shí)候x = - x
計(jì)算,則右側(cè)將引發(fā)陷阱并觸發(fā)調(diào)試器.

TA貢獻(xiàn)1839條經(jīng)驗(yàn) 獲得超15個(gè)贊
是的,程序可能會(huì)崩潰。例如,可能會(huì)出現(xiàn)陷阱表示(無(wú)法處理的特定位模式),這些表示可能會(huì)導(dǎo)致CPU中斷,而未處理的則可能導(dǎo)致程序崩潰。
(6.2.6.1在后期的C11草案中說(shuō))某些對(duì)象表示不需要表示對(duì)象類(lèi)型的值。如果對(duì)象的存儲(chǔ)值具有這樣的表示形式,并且由不具有字符類(lèi)型的lvalue表達(dá)式讀取,則該行為是未定義的。如果這樣的表示是由一個(gè)副作用產(chǎn)生的,該副作用通過(guò)不具有字符類(lèi)型的lvalue表達(dá)式修改對(duì)象的全部或任何部分,則該行為是未定義的。50)這種表示稱(chēng)為陷阱表示。

TA貢獻(xiàn)1878條經(jīng)驗(yàn) 獲得超4個(gè)贊
unsigned int x
x -= x
- 4 回答
- 0 關(guān)注
- 873 瀏覽
添加回答
舉報(bào)