二維數組(解引用、指針數組、數組的指針)——C語言


二維數組

在說二維數組前先來說下一維數組中的指針數組和和數組的指針

一、一維數組中指針數組數組指針的區別

指針數組:

1 int *p[5];

[]的優先級比*高,首先它是一個數組,它的大小是5,它里面存放的數據類型是int *,也就是整型指針。 所以它叫指針數組,講到底這個p是一個數組,數組內的元素是5個指針,而數組內的每一個指針指向一個int型的變量

數組的指針:

int (*p)[5];

 首先p是一個指針,指向大小為5的數組,因此這叫數組的指針,定義了一個指向5個元素的一維數組的指針。(括號優先)

二、兩者在賦值時的區別

指針數組的賦值

 1 #include <stdio.h>
 2 
 3 main()  4 {  5     int *p[5];  6     int a = 10;  7     
 8     p[0] = &a;  9     printf("%d", *p[0]); 10 }

 

數組的指針的賦值

1 main() 2 { 3     int (*p)[5]; 4     int a[5] = {1, 2, 3, 4, 5}; 5 
6     p = &a; 7     printf("%d", *p[0]); 8 }

 

三、關於數組的地址(這里只討論一維\二維數組)

一維數組

1 int a[5];

a表示的是數組的首地址,a等價於&a[0]

 

二維數組

1 int a[2][2] = {1, 2, 3, 4};

a表示的整個數組的首地址,a[0]表示的是第一行的首地址,這兩者者在數值上是一樣的,但含義不同(或者說類型不同),數組名a是對於整個數組,a[0]是對於第一行

 

對二者(a、a[0])的地址是否相同進行驗證

 1 #include <stdio.h>
 2 
 3 int main()  4 {  5     int a[2][2] = {1, 2, 3, 4};  6 
 7     printf("%p\n%p\n", a, a[0]);  8 
 9     return 0; 10 }

運行結果

 

在用數組的地址進行賦值的時候,雖然三者值相同,但是三者不可隨意混用(以int a[2][2]為例)

a--------是int (*)[2]型

a[0]-----是int *型

 

對於a[0]和&a[0][0],兩個類型都是int *型的,所以下述兩種賦值方法等價

第一種:

1 int a[2][2] = {1, 2, 3, 4}; 2 int *p; 3 p = a[0];

第二種:

1 int a[2][2] = {1, 2, 3, 4}; 2 int *p; 3 p = &a[0][0];

 對於int a[2][2]來說,如果將a[0]改為&a[0],那么&a[0]和a的類型相同,都為int (*)[2]類型,下面以int a[5][5]為例,列出了二維數組的元素在不同方式表達下的不同類型

也可以用一維指針數組來保存二維數組中某個元素的地址

1 int a[2][2] = {1, 2, 3, 4}; 2 int *p[2]; 3 p[0] = &a[0][0]; 4 printf("%d", *p[0]);

 

四、二維數組的解引用

以二維數組a[2][3]={1, 2, 3, 4 ,5, 6};為例(第一維是行,第二維是列)

第一種:*(*a+1)--------等價於a[0][1],因為*的優先級比+高,所以先解引用,進入第二維在第二維里面地址+1,再次解引用得到元素值

第二種:*(*(a+1))------等價於a[1][0],比上面第一種多加了一個括號,括號優先級最高,先+1移動地址(注意是在第一維里面移動),然后解引用進入第二維,再解引用得到元素的值

第三種:*(&a[0][0]+1)--等價於a[0][1],這里使用了&取地址符,將原本表示第一個元素的a[0][0]返回到第二個維度,然后第二維地址+1,再解引用得到元素的值

 

為方便讀者理解下面上圖

 

補充:

請讀者先看下面的代碼

1 #include <stdio.h>
2 
3 main() 4 { 5     int a[2][3] = {1, 2, 3, 4, 5, 6}; 6 
7     printf("%d***%d", *(a[1]+1), (*a+1)[1]); 8 }

 *(a[1]+1)--------表示的是a[1][1]的值

(*a+1)[1]--------表示的是a[0][2]的值

為了方便描述先退回一維數組,以int a[5]來說,a表示的數組a的首地址,a[2]表示在a的基礎上移動2個地址(注意a的類型是int *型的,再解引用得到元素的值,意思是a[2]

實際上包含了兩步,第一步地址移動,第二步解引用得到元素的值(注意第二步,有點隱式轉換的意思,經常被人忽略)

現在來解釋上面的二維數組就容易多了

先來看第一個*(a[1]+1),a[1]代表第二行的首地址,注意這里的維度已經是第二維度了,然后括號優先第二維地址+1,最后解引用得到元素的值

 

來看第二個(*a+1)[1],這里提一句,因為[]的優先級是比*高的所以這里的括號不能去掉,第一步先解引用進入第二維度(*優先級高於+),然后第二維地址+1,然后再在當前基礎上再移動一次地址,最后解引用

得到元素的值,這里可能有點繞,換個說法就是[1]是在當前維度進行移動,然后解引用(“當前維度”有點不太嚴謹,為了方便理解先將就這么用了)

 

拿a[2][1]來說,一共有四步,其中包含了兩次地址移動,兩次解引用,執行順序是:地址移動->解引用->地址移動->解引用(這里提一句,[]的結合性是左結合的,所以在移動的時候先移動行(第一維)再移動列(第二維),小聲BB

詳細步驟:第一步:在當前維度地址+2,因為a的維度是第一維,所以是第一維地址+2,即行+2

     第二步:解引用進入第二維度

     第三步:在當前維度地址+1,因為這時已經進入第二維,所以第二維地址+1,即列+1

     第四步:解引用得到元素的值  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM