C語言指標與二維陣列資料詳解(附示例程式碼)
二維陣列在概念上是二維的,有行和列,但在記憶體中所有的陣列元素都是連續排列的,它們之間沒有“縫隙”。本文是本站小編搜尋整理的關於C語言指標與二維陣列資料詳解(附示例程式碼),供參考學習,感興趣的小夥伴們可以參考一下!想了解更多相關資訊請持續關注我們應屆畢業生考試網!
以下面的二維陣列 a 為例:
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
從概念上理解,a 的分佈像一個矩陣:
0 1 2 3
4 5 6 7
8 9 10 11
但在記憶體中,a 的分佈是一維線性的,整個陣列佔用一塊連續的記憶體:
C語言中的二維陣列是按行排列的,也就是先存放 a[0] 行,再存放 a[1] 行,最後存放 a[2] 行;每行中的 4 個元素也是依次存放。陣列 a 為 int 型別,每個元素佔用 4 個位元組,整個陣列共佔用 4×(3×4) = 48 個位元組。
C語言允許把一個二維陣列分解成多個一維陣列來處理。對於陣列 a,它可以分解成三個一維陣列,即 a[0]、a[1]、a[2]。每一個一維陣列又包含了 4 個元素,例如 a[0] 包含 a[0][0]、a[0][1]、a[0][2]、a[0][3]。
假設陣列 a 中第 0 個元素的地址為 1000,那麼每個一維陣列的首地址如下圖所示:
為了更好的理解指標和二維陣列的關係,我們先來定義一個指向 a 的指標變數 p:
int (*p)[4] = a;
括號中的*表明 p 是一個指標,它指向一個數組,陣列的型別為int [4],這正是 a 所包含的每個一維陣列的型別。
[ ]的優先順序高於*,( )是必須要加的,如果赤裸裸地寫作int *p[4],那麼應該理解為int *(p[4]),p 就成了一個指標陣列,而不是二維陣列指標,這在《C語言指標陣列》中已經講到。
對指標進行加法(減法)運算時,它前進(後退)的步長與它指向的資料型別有關,p 指向的資料型別是int [4],那麼p+1就前進 4×4 = 16 個位元組,p-1就後退 16 個位元組,這正好是陣列 a 所包含的每個一維陣列的長度。也就是說,p+1會使得指標指向二維陣列的下一行,p-1會使得指標指向陣列的上一行。
陣列名 a 在表示式中也會被轉換為和 p 等價的指標!
下面我們就來探索一下如何使用指標 p 來訪問二維陣列中的每個元素。按照上面的定義:
1) p指向陣列 a 的開頭,也即第 0 行;p+1前進一行,指向第 1 行。
2) *(p+1)表示取地址上的'資料,也就是整個第 1 行資料。注意是一行資料,是多個數據,不是第 1 行中的第 0 個元素,下面的執行結果有力地證明了這一點:
#include <stdio.h>
int main(){
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int (*p)[4] = a;
printf("%d", sizeof(*(p+1)));
return 0;
}
執行結果:
16
3) *(p+1)+1表示第 1 行第 1 個元素的地址。如何理解呢?
*(p+1)單獨使用時表示的是第 1 行資料,放在表示式中會被轉換為第 1 行資料的首地址,也就是第 1 行第 0 個元素的地址,因為使用整行資料沒有實際的含義,編譯器遇到這種情況都會轉換為指向該行第 0 個元素的指標;就像一維陣列的名字,在定義時或者和 sizeof、& 一起使用時才表示整個陣列,出現在表示式中就會被轉換為指向陣列第 0 個元素的指標。
4) *(*(p+1)+1)表示第 1 行第 1 個元素的值。很明顯,增加一個 * 表示取地址上的資料。
根據上面的結論,可以很容易推出以下的等價關係:
a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)
【例項】使用指標遍歷二維陣列。
#include <stdio.h>
int main(){
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*p)[4];
int i,j;
p=a;
for(i=0; i<3; i++){
for(j=0; j<4; j++) printf("%2d ",*(*(p+i)+j));
printf("");
}
return 0;
}
執行結果:
0 1 2 3
4 5 6 7
8 9 10 11
指標陣列和二維陣列指標的區別
指標陣列和二維陣列指標在定義時非常相似,只是括號的位置不同:
int *(p1[5]); //指標陣列,可以去掉括號直接寫作 int *p1[5];
int (*p2)[5]; //二維陣列指標,不能去掉括號
指標陣列和二維陣列指標有著本質上的區別:指標陣列是一個數組,只是每個元素儲存的都是指標,以上面的 p1 為例,在32位環境下它佔用 4×5 = 20 個位元組的記憶體。二維陣列指標是一個指標,它指向一個二維陣列,以上面的 p2 為例,它佔用 4 個位元組的記憶體。
-
2017全國計算機二級《C語言》考試題及答案
在備考複習階段,需通過大量試題練習,加深對考點的理解和掌握。以下是本站小編搜尋整理的一份全國計算機二級《C語言》考試題及答案,供參考練習,希望對大家有所幫助!想了解更多相關資訊請持續關注我們應屆畢業生考試網!一、選擇題1).我們所寫的每條C語句,經過編譯最...
-
關於C語言精選模擬練習題
C語言是一個有結構化程式設計、具有變數作用域(variablescope)以及遞迴功能的過程式語言。下面是小編為大家整理的關於C語言精選模擬練習題,歡迎參考~5:請編寫一個函式fun,它的功能是:比較兩個字串的長度,(不得呼叫c語言提供的`求字串長度的函式),函式返回較長...
-
2017年計算機二級C語言考前訓練題及答案
計算機二級對於很多考生來說還是比較有難度的,那麼怎樣順利通過二級考試呢?這就需要大家平時多練習和找方法了。以下是本站小編整理的2017年計算機二級C語言考前訓練題及答案,希望對大家有幫助!考前訓練題一1:第1題m個人的成績存放在score陣列中,請編寫函式fun,它...
-
初學C語言的人最常問的幾個問題
C語言是一門通用計算機程式語言,應用廣泛。對於新手來說學習C語言並不是那麼容易,下面是C語言初學者最常問的幾個問題,歡迎閱讀!1.多久能學會程式設計?這是一個沒有答案的問題。每個人投入的時間、學習效率和基礎都不一樣。如果你每天都拿出大把的時間來學習,那麼兩三...