假設有陣列int a=, 我們可是通過一系列的方式訪問它
定義:int *p; p=a;
則p指向了a。此時我們姑且認為a與p等價。
需求使用 a
使用 p
訪問陣列第乙個元素
a[0]
*p同上
*ap[0]
訪問陣列第二個元素
a[1]
*(p+1)
同上*(a+1)
p[1]
將上述陣列轉化為圖,即下圖所示(這裡1是指int的單位大小):
所以對於使用指標來講,*(陣列元素位址) 即可訪問陣列對應元素。
可以清晰的看出a 是陣列a 的位址; 也是陣列a 第乙個元素的位址。所以該位址有雙重的身份,這雙重身份可以被計算機解讀,取決於陣列在c語言中的特殊結構設定。兩個身份並不矛盾,可以理解為同一身份。
為了更清楚的理解,我們寫了乙個小例項,定義了乙個陣列a,用指標 p 來指向 a 執行結果如下:
int
*p=a;
//runing...結果:
&a:6487376 a:
6487376
*a:1
&p:6487576 p:
6487376
*p:1
&a 取到的是陣列a 的陣列位址(第一重身份), a 是陣列第乙個元素位址(第二重身份),均為:6487376,兩個身份一致,至於不同的解析取決於 c 的陣列結構定義。
而指標 p 來講,p 有自己的位址(並且有自己的 大小 和 匯流排 有關),p指向的是(!!可能是!!)陣列的位址(不排除是第乙個元素的位址的可能),(當然這也不重要,就看官方是怎麼詮釋而已,不影響理解)。
故名思意,該形式首先是個陣列,但是陣列的每個元素都是指標。
設有陣列: int b[4][3] = ;
1.我們可以將它理解為兩個巢狀的陣列,首先第一陣列即是b[4], b[4]的每乙個元素都是乙個長度為[3]的陣列首位址。
2.首先**b[4],可以將b[4] 理解為一維陣列,類似上面所述。所以b 是該陣列的b[4] 的位址; 也是陣列b[4] 第乙個元素的位址,該元素可以通過兩種書寫方式取得:b[0]、*b 。12
343.在1.中我們假設了,b[4]的每乙個元素都是巢狀陣列中的子陣列首位址,設第乙個子陣列為b1[3], 一維陣列,首位址(第乙個元素位址)為b1, 那麼2.中我們取得的 b[0] (或*b),即是b1。(見下圖,僅展示前b[3])
4. 欲取得b1中的元素(設b1中第乙個元素),我們可以通過,b1[0]、*b1, 兩種寫法。同理代入b,完整的寫法可以推出:b[0][0] 、*(b[0])、(*b)[0] 、**b。
5. 經過驗證,4.中所述寫法完全可以編譯執行,完美取得b[4][3] 中的第乙個元素。所以基本驗證了我們的假設:b矩陣屬於乙個巢狀陣列。b是矩陣首位址、是矩陣第乙個子陣列首位址,但是矩陣首位址(矩陣第乙個元素位址)中存放的是 矩陣第乙個子陣列首位址(子陣列第乙個元素位址),只有矩陣的子陣列中,才存放著具體的元素。
6. 俄羅斯套娃。在b是[4][3], 矩陣的前提下,設b的位址(&b)為:6487424、b存放的位址是:6487424、取得b存放的位址中的元素(b)我們發現竟然是:6487424, 但是當在一次取b位址中的元素(**b)我們發現卻是 1 。
即是:&b == b ,b == *b , 但是 *(*b) != b 。乙個記憶體位置上 存放著 該位置的位址
首先從上一章節一維陣列中,我們知道 &b == b 是對陣列結構的特殊詮釋。但 b == *b ,就可能是 c 語言中 ,對二維陣列的不同的額外特殊詮釋。只有當對位址多次取值,才能真正取得位址上的元素 1 。
7. 我們甚至可以將二維陣列直接利用指標的方式轉化為一維陣列,p=&b[0][0];
語句相當簡單,就是直接指向矩陣的第乙個元素。
8. 我們還可以講:指向二維陣列的指標的定義方式,是定義乙個指向第一層巢狀陣列(在例子中即是指向 b[4])的指標。陣列很重要的屬性是型別,陣列型別決定了為每個元素分配記憶體的大小,第一層巢狀陣列而言,矩陣b[4][3] 的列向量就顯得尤為重要,因為列數表明第一層巢狀陣列每個元素的大小(sizeof( type x ) * 列數
)。
9. 那麼模擬一維陣列指標的定義:type * p = a;
10. 推出二維陣列指標的定義為:type (*q)[m] = b, 其中type b[m] ;
&b is:
6487424
b is:
6487424
*b is:
6487424
**b is:1|
6487424
|6487428
|6487432
|6487436
|6487440
|6487444
|6487448
|6487452
|6487456
|6487460
|6487464
|6487468
int(
*l)[3]
=b; l is:
:6487424
*l is:
6487424
*(l+1)
:6487436
*(l+2)
:6487448
*(l+2)
[1]:
10**l is:1*
*(l+1)
:4**
(l+2):
7*(*
(l+2)+
1):8
驗證其他寫法:
*(b[0]
):1(
*b)[0]
:1轉化為一維陣列:
p=&b[0]
[0];
p is:
6487424
*p is:1*
(p+1):
2*(p+2):
3*(p+5):
6------
----
----
----
----
----
----
--process exited after 128.5 seconds with return value 0
請按任意鍵繼續.
..
最後補充一下,大佬的
4.指向二維陣列的指標陣列:
type (*parray[num])[column];
其中column為二維陣列的維度。num為指標的個數,定義時如果直接賦值的話,可以不指定num的大小。
例如定義乙個指標arr1的指標陣列,陣列的大小為5:
int (*parr1[5])[2];
parr1[0]=arr1;
printf("%d",parr1[0][2][1]); // 輸出為:6
另外乙個例子:
static
const
char _keyboard_lower[4]
[10]=
,,,,
};static
const
char _keyboard_upper[4]
[10]=
,,,,
};static
const
char _keyboard_num[4]
[10]=
,,,,
};static
const
char
(*_keyboard_char)
[10]=
;
二維陣列 二維陣列和指標
include using namespace std int main 如上面這段程式所示,通過取位址符 指標 p 獲得了變數 a 的位址,那麼解引用符 就可以從 p 中得到變數 a 的值。也就是說,p a和 p a是等價的。p 是變數 a 的位址,從 p 中就可以取出 a 的值。反之,能從 p ...
二維陣列與二維指標
1.二維陣列的儲存是線性的,可以通過一維指標的方式訪問。如一下 int map 5 5 int mapd map 0 0 則 map i j mapd i 5 j 而利用二維陣列線性儲存的特性,可以將二維陣列當作一維指標方便的在函式之間傳遞 如 將乙個二維陣列賦值給乙個動態二維陣列,引數設定為一維指...
二維指標和二維陣列
二維指標和二維陣列有三種形式 1,type ptr 2,type ptr或者type prt 3,type prt 三種形式意思相近,也有區別。首先三種形式都能表示二維的資料結構。1,type ptr 表示乙個指向指標的指標 但是在一開始宣告的時候 type ptr ptr到底指向幾個指標是不知道的...