c c 中索引超出陣列邊界問題

2021-08-21 07:29:36 字數 1903 閱讀 1275

c/c++沒有陣列

在其它高階語言裡,不管是定義(宣告)還是引用, a[i] 或 a[3] 都是乙個整體。在 c/c++ 裡,卻是乙個表示式: a[i] 是運算子  連線兩個實體 a 和 i 。

說 c/c++ 並沒有陣列 , 有以下幾條理由。

理由一: c 裡沒有陣列形式。

「陣列」名 a 本身就是乙個指標,與常規指標不同的是,它是乙個不能移動的所謂常指標。

如在函式外有定義:

float a[3] = ;

首先在初始化資料段分配一塊能容納三個 float 數的空間,並填入三個初始值,然後定義乙個名為 a 指向 float 資料流的常指標,並使其指向該區域的首位元組。

理由二:「陣列」的定義,其實最終是對指標的定義。

說「指向 float 資料流」,和說「指向 float 型陣列」,是兩個概念。共性是,計算偏移量(我不說移動,因為常指標是不能移動的。)時,計算單位都是 float 型資料的位元組數。但是,陣列是有邊界的,你的下標不能超出邊界。而偏移量可以超出資料流的邊界(後果自負)。

很多書裡說, c 「陣列」沒有邊界檢查,是為了執行效率。但是,對邊界的檢查,系統開銷並不大。 c 裡的「陣列」其實是個資料流,它的邊界只有一頭:常指標所指向的下邊界。

理由三:陣列名和下標竟然可以互換。

我們要訪問上面那個資料流的第 2 個資料,可以使用 a[1] ,也可以使用 *(a + 1) 。兩者完全等價。我懷疑, c 的作者所提供的 a[i] ,僅僅是 *(a + i) 的同義詞。按照加法交換率,顯然, *(a + i) 等於 *(i + a) 。那 i[a] 是不是也等於 a[i]呢?測試結果:等於。更奇怪的是,不但 i[a] 等於 a[i] , 1[a] 也等於 a[1] !

看看下面的相等關係:

a[1] 等於 *(a + 1) 等於 *(1 + a) 等於 1[a]

上面的懷疑或許有點道理了。

理由四: a[i] 無非是 *(a + i) 的同義詞。

對「陣列」的訪問,最終總是通過指標的。其基本形式是: *(a + i) 。

「陣列」名是乙個常指標,總是指向該區域的首址。「下標」其實是乙個邏輯偏移量。說它是「邏輯」的,意思是在計算時,需要乘以步長(資料的長度)。但是,這個「乘法」對你是透明的,不必關心它。指向所訪問資料的是常指標「加」偏移量。

在 x86 系列 cpu 的指令系統裡,有乙個基址變址定址方式。這種定址方式和 c 對「陣列」的訪問方式很相似。常指標相當於基址,偏移量相當於變址。

我懷疑,這個基址變址定址方式是為 c 訪問「陣列」而增加的。

理由五: c 「陣列」沒有上邊界。

對下面的定義

float a[3] = ;

我們不僅可以訪問 a[0] 、 a[1] 和 a[2] ,還可以訪問 a[3] 、 a[4] 等。 c 陣列不知道自己的一畝三分到**為止。用c/c++ 開發,與用其它語言不同,程式設計員必須記住自己定義的陣列有多大。自己的家沒有柵欄,跑到鄰居割韭菜沒人管,但後果自負。

理由六:對「多維陣列」的訪問總是可化解成對「一維陣列」的方式。

誠然,不管是用哪種語言程式設計,最終生成的目標程式碼中,陣列總是被轉換成一塊連續的儲存區(即它是線狀的)。不同的是,在 c 原始碼裡,所有的陣列,不管是幾維的,都是線狀的。在原始碼層面,都可以看作是一維的。定義了

int a[3][4];

可以用 a[2][3] ,也可以用 a[11] 訪問其第 2 行、第 3 列元素。

結論

c 裡使用下標運算子  ,無非是使指向一串等型別元素的指針對該區域的操作看起來像運算元組而已。沒有這東西,習慣了其它高階語言陣列操作的編碼員會覺得不習慣。

陣列邊界問題

先來看一段程式吧,在程式中講問題 include int prime int x int main while i 301 for i 0 i 300 i for i 0 i 300 i if 1898 sum return0 int prime int x if 2 count else for ...

二分查詢中的邊界問題 1, 1, ,

題目描述 統計乙個數字在排序陣列中出現的次數。分析 原來一直對二分法很模糊,對mid 1,還是mid,決定這兩個差不多,今天自己打臉了,控制的不精準就是錯誤。把邊界確定更加準確點,left,end 確定為閉區間,只要不在這個區間,就 1或者 1,不要模糊,不要模糊兩可 class solution ...

TCP通訊協議(中)字串邊界問題

案例來自張子陽的 net之美 經消化後放在這。如果希望字串整齊傳輸,那麼需要提出乙個 標誌 比如下面傳輸 今天聖誕,祝大家節日快樂!在字串前加入 length 13 有點類似資料報的幀頭幀尾,有效資料總是緊跟其後。得到有效資料的長度後,可以進行擷取 列印。有效資料的長度可以自定義,例子中是13,即每...