在說二維數組前先來講下一維數組中的指針數組和和數組的指針數組
指針數組:spa
1 int *p[5];
[]的優先級比*高,首先它是一個數組,它的大小是5,它裏面存放的數據類型是int *,也就是整型指針。 因此它叫指針數組,講到底這個p是一個數組,數組內的元素是5個指針,而數組內的每個指針指向一個int型的變量3d
數組的指針:指針
int (*p)[5];
首先p是一個指針,指向大小爲5的數組,所以這叫數組的指針,定義了一個指向5個元素的一維數組的指針。(括號優先)code
指針數組的賦值blog
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 }
數組的指針的賦值io
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 }
一維數組class
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
第四步:解引用獲得元素的值