第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

(為什么)使用未初始化的變量未定義的行為?

(為什么)使用未初始化的變量未定義的行為?

C C++
千巷貓影 2019-05-30 16:03:58
(為什么)使用未初始化的變量未定義的行為?如果我有:unsigned int x;x -= x;很明顯x 應在這個表達式之后是零,但是無論我看哪里,他們都說行為代碼的值是未定義的,而不僅僅是x(直至減法之前)。兩個問題:是行為這段代碼確實沒有定義?(例如。代碼是否會在兼容的系統(tǒng)上崩潰(或者更糟)?如果是這樣,為什么C是否說行為是未定義的,當非常清楚的是x這里應該是零?即什么是優(yōu)勢不定義這里的行為?顯然,編譯器可以簡單地使用管它呢它認為在變量中“方便”的垃圾值,它將按預期工作.這種方法有什么問題嗎?
查看完整描述

4 回答

?
梵蒂岡之花

TA貢獻1900條經驗 獲得超5個贊

是的,這種行為是沒有定義的,但其原因與大多數人所知道的不同。

首先,使用統(tǒng)一值本身并不是未定義的行為,但值只是不確定的。如果值恰好是類型的陷阱表示,則訪問此值的是UB。無符號類型很少有陷阱表示,因此在這方面相對安全。

使行為無法定義的是變量的一個附加屬性,即它“可以用register這就是它的地址永遠不會被接受。這樣的變量被特別對待,因為有些架構有真正的CPU寄存器,它們有一種額外的狀態(tài),這種狀態(tài)是“未初始化的”,并且與類型域中的值不相對應。

編輯:標準的相關短語為6.3.2.1p2:

如果lvalue指定可以用寄存器存儲類聲明的具有自動存儲持續(xù)時間的對象(從未使用其地址),且該對象未初始化(未使用初始化器聲明,且未在使用前對其執(zhí)行賦值),則行為未定義。

為了讓它更清楚,下面的代碼在任何情況下都是合法的:

unsigned char a, b;memcpy(&a, &b, 1);a -= a;
  • 這里的地址

    a

    b

    所以它們的價值是不確定的。
  • unsigned char

    從未有不確定值只是未指定的陷阱表示,任何

    unsigned char

    可能會發(fā)生。
  • 最后

    a 

    持有價值

    0.

編輯2: ab具有未指定的值:

3.19.3 未指定值
在本國際標準不要求在任何情況下選擇值的相關類型的有效值


查看完整回答
反對 回復 2019-05-30
?
慕標琳琳

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ā)調試器.


查看完整回答
反對 回復 2019-05-30
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

是的,程序可能會崩潰。例如,可能會出現陷阱表示(無法處理的特定位模式),這些表示可能會導致CPU中斷,而未處理的則可能導致程序崩潰。

(6.2.6.1在后期的C11草案中說)某些對象表示不需要表示對象類型的值。如果對象的存儲值具有這樣的表示形式,并且由不具有字符類型的lvalue表達式讀取,則該行為是未定義的。如果這樣的表示是由一個副作用產生的,該副作用通過不具有字符類型的lvalue表達式修改對象的全部或任何部分,則該行為是未定義的。50)這種表示稱為陷阱表示。


查看完整回答
反對 回復 2019-05-30
?
UYOU

TA貢獻1878條經驗 獲得超4個贊

C標準并沒有說使用未初始化的自動存儲持續(xù)時間對象的值是未定義的行為。C 1999標準在6.7.8 10中說:“如果沒有顯式初始化具有自動存儲持續(xù)時間的對象,那么它的值是不確定的?!?本段繼續(xù)定義靜態(tài)對象是如何初始化的,因此我們關注的唯一未初始化對象是自動對象。)

3.17.2將“不定值”定義為“未指定值或陷阱表示”。3.17.3將“未指明價值”定義為“本國際標準未規(guī)定在任何情況下選擇價值的相關類型的有效值”。

所以,如果未初始化unsigned int x具有未指定的值,則x -= x必須產生零。這就留下了一個問題,那就是它是否是一個陷阱表示法。訪問陷阱值確實會導致未定義的行為,如6.2.6.1 5所示。

某些類型的對象可能有陷阱表示,例如浮點數的信令nans.但無符號整數是特殊的。根據6.2.6.2,無符號int的每個N值位表示2的冪,值位的每個組合表示0到2之間的值之一。N-1。因此,由于填充位中的某些值(例如奇偶校驗位),無符號整數只能具有陷阱表示。

如果在目標平臺上,無符號int沒有填充位,那么未初始化的無符號int不能有陷阱表示,而且使用它的值不會導致未定義的行為。


查看完整回答
反對 回復 2019-05-30
  • 4 回答
  • 0 關注
  • 864 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號