3 回答

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

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

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