C和C++中所謂的陣列
在其它高階語言裡,不管是定義(宣告)還是引用, a[i] 或 a[3] 都是一個整體。在 C/C++ 裡,卻是一個表示式: a[i] 是運算子 [] 連線兩個實體 a 和 i 。
說 C/C++ 並沒有陣列 , 有以下幾條理由。
理由一: C 裡沒有陣列形式。
“陣列”名 a 本身就是一個指標,與常規指標不同的是,它是一個不能移動的所謂常指標。
如在函式外有定義:
float a[3] = {1.0, 2.0, 3.0};
首先在初始化資料段分配一塊能容納三個 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] = {1.0, 2.0, 3.0};
我們不僅可以訪問 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 裡使用下標運算子 [] ,無非是使指向一串等型別元素的指標對該區域的操作看起來像運算元組而已。沒有這東西,習慣了其它高階語言陣列操作的編碼員會覺得不習慣。
相關文章
- C++ 陣列的 auto 和 decltypeC++陣列
- c++中的陣列C++陣列
- C/C++ 二維陣列的理解(多維陣列)C++陣列
- C++謂詞C++
- C++陣列 字串C++陣列字串
- C++ 陣列宣告和初始化C++陣列
- C++陣列長度C++陣列
- c++陣列排序插入C++陣列排序
- C++ Break、Continue 和 陣列操作詳解C++陣列
- C++陣列的連續性C++陣列
- C/C++ 讀入一個整型陣列,陣列大小未知C++陣列
- C++ ——vector陣列筆記C++陣列筆記
- C++獲取陣列的長度C++陣列
- c++筆記_多維陣列C++筆記陣列
- c++遍歷陣列的多種方式C++陣列
- C++ 獲取陣列大小、多維陣列操作詳解C++陣列
- C/C++獲取二維陣列行列數C++陣列
- 獲取C/C++字串、字元陣列長度C++字串字元陣列
- C++陣列預設初值問題C++陣列
- C++ 煉氣期之陣列探幽C++陣列
- C++ 使用 new 建立二維陣列C++陣列
- C++用new建立二維陣列的方法C++陣列
- C++陣列在年曆列印中的運用C++陣列
- c++中string類物件和字元陣列之間的相互轉換C++物件字元陣列
- C陣列和指標陣列指標
- 劍指offer——陣列中的逆序對C++(75%)陣列C++
- 劍指offer——把陣列排成最小的數C++陣列C++
- c++ -- 二維陣列引數傳遞C++陣列
- SWIG 打包C++陣列供python呼叫 tcyC++陣列Python
- C++特別數的和(列舉)C++
- C/C++ 陣列連結串列表示式計算C++陣列
- 面試最常問的陣列轉樹,樹轉陣列 c++ web框架paozhu實現面試陣列C++Web框架
- [C++之旅] 14 物件成員與物件陣列C++物件陣列
- C++基礎回顧4——動態陣列C++陣列
- LeetCode C++ 56. Merge Intervals【排序/陣列】中等LeetCodeC++排序陣列
- C++ 練氣期之二維陣列與矩陣運算C++陣列矩陣
- Javascript - 陣列和陣列的方法JavaScript陣列
- C++ 一元謂詞對應的lambda表示式C++
- 【C/C++】C和C++11之enum列舉的使用細節C++