概述
在C語言中,當(dāng)你有一個(gè)指向數(shù)組中某個(gè)元素的指針時(shí),你可以對該指針執(zhí)行某些算術(shù)運(yùn)算,例如加法或減法。這些運(yùn)算可以用來遍歷數(shù)組中的元素,如ptr[i]等價(jià)于*(ptr + i)。然而,如果你的操作使得指針指向了數(shù)組以外的位置(除了數(shù)組結(jié)束位置之后的一個(gè)位置之外),那么這個(gè)指針的行為就是未定義的。
例如:
如果ptr指向數(shù)組的第一個(gè)元素,那么ptr + 1將指向第二個(gè)元素。
如果ptr指向數(shù)組的最后一個(gè)元素,那么ptr + 1將指向數(shù)組結(jié)束之后的一個(gè)虛構(gòu)位置,這是允許的,但是試圖訪問該位置(如*(ptr + 1))將導(dǎo)致未定義行為。
如果ptr指向數(shù)組的最后一個(gè)元素,那么ptr + 2指向的位置超出了數(shù)組的范圍,這將導(dǎo)致未定義行為。
未定義行為意味著編譯器可以做出任何事情,包括但不限于程序崩潰、數(shù)據(jù)損壞或其他不可預(yù)測的結(jié)果。因此,在編寫涉及指針操作的代碼時(shí),確保指針始終在安全范圍內(nèi)是非常重要的。在實(shí)際編程中,常常會(huì)用到邊界檢查來防止這類問題的發(fā)生。
詳述
創(chuàng)建一個(gè)指向數(shù)組末尾之后的指針在標(biāo)準(zhǔn)中是有明確定義的,并且本規(guī)則允許這種操作。但是,引用通過這種方式創(chuàng)建的指針會(huì)導(dǎo)致未定義的行為,并且此規(guī)則禁止這樣做。
本規(guī)則適用于所有形式的數(shù)組索引:
整數(shù)表達(dá)式 + 整數(shù)表達(dá)式
指針表達(dá)式 + 整數(shù)表達(dá)式
指針表達(dá)式 += 整數(shù)表達(dá)式
指針表達(dá)式 -= 整數(shù)表達(dá)式
++ 指針表達(dá)式
-- 指針表達(dá)式
指針表達(dá)式++
指針表達(dá)式--
整數(shù)表達(dá)式 [指針表達(dá)式]
指針表達(dá)式 [整數(shù)表達(dá)式]
注意:對于指針?biāo)阈g(shù)的目的,標(biāo)準(zhǔn)將不是數(shù)組成員的對象視為具有單個(gè)元素的數(shù)組。
理由
雖然一些編譯器可以在編譯時(shí)確定數(shù)組邊界是否超出,但在運(yùn)行時(shí)通常不會(huì)對無效數(shù)組下標(biāo)進(jìn)行檢查。使用無效數(shù)組下標(biāo)可能導(dǎo)致程序出現(xiàn)錯(cuò)誤行為。
由于它們不容易通過靜態(tài)分析或手動(dòng)審查來檢查,因此運(yùn)行時(shí)推導(dǎo)出的數(shù)組下標(biāo)值最令人擔(dān)憂。如果可能的話,應(yīng)該提供代碼以檢查此類下標(biāo)值的有效性,并根據(jù)需要采取適當(dāng)?shù)男袆?dòng)。
如果從上述表達(dá)式之一獲得的結(jié)果不是一個(gè)指向由指針表達(dá)式所指向的數(shù)組元素或一個(gè)超過該數(shù)組末尾的一個(gè)元素的指針,則其行為是未定義的。有關(guān)更多信息,請參閱C90第6.3.6節(jié)、C99第6.5.6節(jié)。
多維數(shù)組是“數(shù)組的數(shù)組”。本規(guī)則不允許導(dǎo)致指針指向不同子數(shù)組的指針?biāo)阈g(shù)。不應(yīng)使用數(shù)組下標(biāo)跨越“內(nèi)部”邊界的數(shù)組下標(biāo),因?yàn)檫@樣的行為是未定義的。
示例
使用+運(yùn)算符也會(huì)違反規(guī)則18.4。
int32_t f1( int32_t * const a1, int32_t a2[10][1]) { /* Compliant/non-Compliant depending on the value of a1 */ int32_t *p = &a1[3]; return*(a2+9);/*Compliant*/ } void f2(void) { int32_t data = 0; int32_t b = 0; int32_t c[10] = {0}; // 5-element array of 2-element arrays of int32_t int32_t d[5][2] = {0}; int32_t *p1 = &c[0]; //Compliant int32_t *p2 = &c[10]; // Compliant - points to one beyond int32_t *p3 = &c[11]; // Non - compliant - undefined, points to two beyond data = *p2; data = f1(&b, c); data = f1(c, c); p1++; /*Compliant*/ c[-1] = 0; /*Non-Compliant - undefined, array bounds exceeded*/ data = c[10]; /*Non-Compliant - undefined,dereference of address one beyond*/ d[3][1] = 0; /*Compliant*/ data = *(*(d + 3) + 1); /*Compliant*/ data = d[2][3]; /*Non-compliant - undefined, internal boundary exeeded*/ p1 = d[1]; data = p1[1]; }
-
C語言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137775 -
指針
+關(guān)注
關(guān)注
1文章
481瀏覽量
70611 -
運(yùn)算符
+關(guān)注
關(guān)注
0文章
172瀏覽量
11115
原文標(biāo)題:Rule18.1 指針運(yùn)算符的結(jié)果應(yīng)指向與該指針運(yùn)算符相同的數(shù)組元素,否則其行為是未定義的
文章出處:【微信號:嵌入式愛好者之家,微信公眾號:嵌入式愛好者之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論