天天看點

C 語言程式設計 — 進階資料類型 — 數組

目錄

前文清單

數組

聲明數組

初始化資料

通路數組元素

二維數組

指向數組的指針

将數組指針作為實參傳入函數

從函數傳回一個數組指針

指針數組

數組名和取數組首位址的差別

《程式編譯流程與 GCC 編譯器》

《C 語言程式設計 — 基本文法》

《C 語言程式設計 — 基本資料類型》

《C 語言程式設計 — 變量與常量》

《C 語言程式設計 — 運算符》

《C 語言程式設計 — 邏輯控制語句》

《C 語言程式設計 — 函數》

《C 語言程式設計 — 進階資料類型 — 指針》

數組是具有相同資料類型,并且按照一定順序排列的一組變量的集合。

數組都是由連續的記憶體空間組成的,最低的位址對應第一個元素,最高的位址對應最後一個元素。數組中的特定元素可以通過索引通路,數組的索引從 0 開始。

C 語言程式設計 — 進階資料類型 — 數組

特征:

有序性:數組元素之間具有固定的先後順序

可索引:通過數組名和下标可以唯一地确定數組中的元素

在 C 中要聲明一個數組,需要指定元素的類型和元素的數量。

其中元素的數量為不可變量,C/C++ 不允許對數組的長度做動态定義。

數組名除了作為數組辨識名稱之外,也表示了該數組存儲空間的首位址,即數組名本身就是數組的記憶體入口位址,指向第一個元素。

一次隻能使用數組中的單個元素,而不能一次使用整個數組。

需要注意的是,使用數組時,需要主動的對數組變量進行邊界檢查。C/C++ 在編譯過程并沒有預設的邊界檢查動作,是以在程式運作過程中當數組下标索引值越界時,并不會立即觸發錯誤,存在潛在的邏輯異常風險。

指定數組長度的初始化:大括号 { } 之間的值的數目不能大于我們在數組聲明時在方括号 [ ] 中指定的元素數目。

不指定數組長度的初始化:數組的長度則為初始化時元素的個數。

對指定的元素進行指派

C 語言程式設計 — 進階資料類型 — 數組

數組元素可以通過數組名稱加索引進行通路。元素的索引是放在方括号内,跟在數組名稱的後邊。

将一個數組元素取出并指派給新的變量:

C 語言支援多元數組。多元數組聲明的一般形式如下:

C 語言程式設計 — 進階資料類型 — 數組

初始化二維數組:

通路二維數組元素:

數組變量名(辨別符)的本質是一個指向數組中第一個元素的常量指針。

如上,變量名 balance 是一個指向記憶體位址 <code>&amp;balance[0]</code> 的指針,即數組 balance 的第一個元素的位址。使用數組名作為常量指針是合法的,反之亦然。是以,<code>*(balance + 4)</code> 是一種通路 balance[4] 資料的合法方式。

如果函數想接受一個數組(實際上是指針數組入口的指針)作為實參,那麼函數必須使用以下三種方式之一來聲明函數的形式參數,每種方式都是告訴編譯器函數将要接收一個整型指針。同樣地,也可以傳遞一個多元數組作為形式參數。

方式 1

方式 2

方式 3

示例:

C 語言不允許函數傳回一個完整的數組,但是可以傳回一個指向數組的指針。注意,C 不支援在函數外部傳回局部變量的位址,除非定義局部變量為 static 變量。

運作:

有一種情況,我們想用數組來存儲指向 int 或 char 或其他資料類型的指針。下面是一個指向整數的指針數組的聲明:

在這裡,把 ptr 聲明為一個數組,由 MAX 個整型指針組成。是以,ptr 中的每個元素,都是一個指向 int 值的指針。

以上述語句為例:

數組名 <code>array</code> 本質是數組首元素的入口位址。

數組首元素的入口位址 <code>&amp;array[0]</code>。

<code>&amp;array</code> 取的是整個數組 array 的首位址。

雖然,<code>&amp;array</code> 和 <code>&amp;array[0]</code> 與 <code>array</code> 的數值相同,但本質卻不同。這一點展現在 +1 偏移量上是非常明顯的。

結論:

在 C 中,幾乎所有使用數組的表達式中,數組名的值是個指針常量,也就是數組第一個元素的位址。 它的類型取決于數組元素的類型: 如果它們是 int 類型,那麼數組名的類型就是 “指向 int 的常量指針“。

在以下兩種場合,數組名并不是用指針常量來表示:1)當數組名作為 <code>sizeof</code> 運算符操作數時,傳回整個數組的長度,而不是指向數組的指針的長度;2)當數組名作為位址運算符 <code>&amp;</code> 的操作數時,傳回的是一個指向整個數組的指針,而不是指向數組首元素的指針。

指針的 <code>+1</code> 是偏移量問題:一個類型為 X 的指針的移動,是以 <code>sizeof(X)</code> 為移動步進的。

<code>array+1</code>:在數組首元素的記憶體位址的基礎上,偏移一個 <code>sizeof(array[0])</code> 機關。上例中,為 <code>0x7fffe3743ae0 + 1 * sizeof(array[0]) == 0x7fffe3743ae0 + 1 * sizeof(int) == 0x7fffe3743ae0 + 4 == 0x7fffe3743ae4</code>。

<code>&amp;array+1</code>:在數組的首位址的基礎上,偏移一個 <code>sizeof(array)</code> 機關。上例中,為 <code>0x7fffe3743ae0 + 1 * sizeof(array) == 0x7fffe3743ae0 + 1 * sizeof(int) * 0x4 == 0x7fffe3743ae0 + 0x16 == 0x7fffe3743af0</code>。

簡而言之,數組名 <code>array</code> 的指針是數組基類型(首元素)的位址長度,而 <code>&amp;array</code> 的指針是整個數組的位址長度。

繼續閱讀