3 回答

TA貢獻(xiàn)1900條經(jīng)驗(yàn) 獲得超5個贊
您說對了:這是未定義的行為,您不能指望它總是在產(chǎn)生0
。
至于為什么在這種情況下看到零的原因:現(xiàn)代操作系統(tǒng)將內(nèi)存分配給進(jìn)程中相對較粗的塊(稱為頁面),這些塊比單個變量大得多(在x86上至少為4KB)。當(dāng)您有一個全局變量時,它將位于頁面上的某個位置。假設(shè)a
類型為,int[][]
并且int
s為系統(tǒng)上的四個字節(jié),a[27][27]
則從的開頭開始約500個字節(jié)a
。因此,只要a
在頁面的開頭附近,訪問a[27][27]
就會被實(shí)際的內(nèi)存支持,并且讀取它不會導(dǎo)致頁面錯誤/訪問沖突。
當(dāng)然,您不能指望這一點(diǎn)。例如,如果a
前面有將近4KB的其他全局變量,那么a[27][27]
它將不由內(nèi)存支持,并且當(dāng)您嘗試讀取它時,過程將崩潰。
即使該過程沒有崩潰,您也不能指望獲得該值0
。如果您在現(xiàn)代的多用戶操作系統(tǒng)上有一個非常簡單的程序,除了分配該變量并打印該值之外什么也不做,您可能會看到0
。在將內(nèi)存移交給進(jìn)程時,操作系統(tǒng)會將內(nèi)存內(nèi)容設(shè)置為某個良性值(通常為全零),以使來自一個進(jìn)程或用戶的敏感數(shù)據(jù)不會泄漏到另一個進(jìn)程或用戶。
但是,不能完全保證讀取的任意內(nèi)存為零。您可以在未分配內(nèi)存的情況下在平臺上運(yùn)行程序,并且會看到從上一次使用開始碰到的任何值。
同樣,如果a
后面跟隨著足夠多的初始化為非零值的其他全局變量,則訪問a[27][27]
將向您顯示恰好在那里的任何值。

TA貢獻(xiàn)1859條經(jīng)驗(yàn) 獲得超6個贊
訪問數(shù)組越界是未定義的行為,這意味著結(jié)果是不可預(yù)知的,從而該結(jié)果a[27][27]存在0是不可靠的。
clang如果我們使用,可以很清楚地告訴你-fsanitize=undefined:
runtime error: index 27 out of bounds for type 'int [4][4]'
一旦你不確定的行為,編譯器真的可以做任何事情,我們甚至還看到其中的例子gcc已經(jīng)翻了有限循環(huán)進(jìn)入一個無限循環(huán)基于圍繞未定義行為的優(yōu)化。雙方clang并gcc在某些情況下可以產(chǎn)生和未定義的指令操作碼,如果它檢測未定義的行為。
為什么它是未定義的行為,為什么越界指針?biāo)阈g(shù)是未定義的行為?提供了很好的原因總結(jié)。例如,結(jié)果指針可能不是有效地址,該指針現(xiàn)在可以指向分配的內(nèi)存頁面之外,您可以使用內(nèi)存映射的硬件而不是RAM等。
存儲靜態(tài)變量的段很可能比您正在分配的數(shù)組或要踩的段大得多,盡管剛好被清零,所以在這種情況下您很幸運(yùn),但行為又完全不可靠。您的頁面大小很可能是4k,對的訪問a[27][27]在該范圍內(nèi),這可能就是為什么您沒有看到分段錯誤的原因。
標(biāo)準(zhǔn)怎么說
在C99標(biāo)準(zhǔn)草案告訴我們這是第不確定的行為6.5.6 加法運(yùn)算符覆蓋指針?biāo)惴ㄊ且粋€數(shù)組訪問來自哪個下來。它說:
將具有整數(shù)類型的表達(dá)式添加到指針或從指針中減去時,結(jié)果將具有指針操作數(shù)的類型。如果指針操作數(shù)指向數(shù)組對象的元素,并且數(shù)組足夠大,則結(jié)果指向與原始元素偏移的元素,以使結(jié)果數(shù)組元素和原始數(shù)組元素的下標(biāo)之差等于整數(shù)表達(dá)式。
[...]
如果指針操作數(shù)和結(jié)果都指向同一數(shù)組對象的元素,或者指向數(shù)組對象的最后一個元素,則求值不會產(chǎn)生溢出;否則,行為是不確定的。如果結(jié)果指向數(shù)組對象的最后一個元素之后,則不應(yīng)將其用作被評估的一元*運(yùn)算符的操作數(shù)。
未定義行為的標(biāo)準(zhǔn)定義告訴我們,該標(biāo)準(zhǔn)對行為沒有任何要求,并指出可能的行為是不可預(yù)測的:
在使用非便攜式或錯誤程序構(gòu)造或錯誤數(shù)據(jù)時的行為,對此國際標(biāo)準(zhǔn)不施加任何要求
注意可能的不確定行為范圍包括完全忽略情況并產(chǎn)生不可預(yù)測的結(jié)果,[...]

TA貢獻(xiàn)1757條經(jīng)驗(yàn) 獲得超8個贊
這是標(biāo)準(zhǔn)的引號,它指定什么是未定義的行為。
J.2不確定行為
即使顯然可以使用給定下標(biāo)訪問對象,數(shù)組下標(biāo)也超出范圍(如在聲明為int a [4] [5]的左值表達(dá)式a [1] [7]中)(6.5.6)。
將指針加或減到數(shù)組對象或整數(shù)類型中或超出數(shù)組對象和整數(shù)類型會產(chǎn)生指向數(shù)組對象正好超出數(shù)組對象的結(jié)果,并用作評估的一元*運(yùn)算符的操作數(shù)(6.5.6)。
在您的情況下,數(shù)組下標(biāo)完全在數(shù)組之外。完全依賴于該值將為零是不可靠的。
此外,整個程序的行為是有問題的。
- 3 回答
- 0 關(guān)注
- 491 瀏覽
添加回答
舉報