4 回答

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

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

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

TA貢獻1878條經驗 獲得超4個贊
unsigned int x
x -= x
- 4 回答
- 0 關注
- 864 瀏覽
添加回答
舉報