指向二維數組的指針與二級指針
今天的話題從一段代碼說起:
#include <stdio.h>
int main(){
int arr[2][2] = {{1, 2}, {3, 4}};
int *p1 = arr[0]; //一級指針
int **p2 = &p1; // 二級指針
int (*p3)[2] = arr; // 指向二維數組的指針
printf("I am p2:%d
", **p2);
printf("I am p3:%d
", **p3);
printf("p2:%p, * of p2:%p
", p2, *p2);
printf("p3:%p, * of p3:%p
", p3, *p3);
return 0;
}
運行結果如下:
我們重點關注的指針變數 p2 與 p3,
p2 是二級指針,指向二維數組中第一個數組中的第一個元素 1.
p3 是指向二維數組的指針
然後我們分別讓他們訪問到 arr 二維數組的第一個數組的第一個元素 1.
printf("I am p2:%d
", **p2);
printf("I am p3:%d
", **p3);
可以看到他們使用相同的運算方法來得到 1.
I am p2:1
I am p3:1
但是他們卻存在著本質的區別。
我們分別列印出 p2, p3, *p2, *p3 的地址。
printf("p2:%p, * of p2:%p
", p2, *p2);
printf("p3:%p, * of p3:%p
", p3, *p3);
p2:0x7fff4a0101b8, * of p2:0x7fff4a0101d0
p3:0x7fff4a0101d0, * of p3:0x7fff4a0101d0
結果是 二級指針 p2 與 *p2 所指向的地址不同。這個應該是符合我們對指針的理解。
而 p3 的結果有些意外,兩次指向同一個地址,那 *p3 豈不是什麼也沒做?
其實也不是。
程序是數據結構加演算法。
我們要知道的是:指針里除了存儲了他要指向的內存地址,其實還有一個信息,
那就是他所指向的地址的類型,這個類型有什麼作用呢?決定了在對指針進行加 1 運算時
指針實際上增加的地址長度。再來看一個例子:
#include <stdio.h>
int main(void){
char *p1 = (char *)1;
printf("I am char pointer p1:%p, p1+1:%p
", p1, p1+1);
int *p2 = (int *)p1;
printf("I am int pointer p2:%p, p2+1:%p
", p2, p2+1);
return 0;
}
結果如下:
I am char pointer p1:0x1, p1+1:0x2
I am int pointer p2:0x1, p2+1:0x5
同樣的一個地址值,賦值給不同的指針變數,在進行加1運算時增加的長度不同。
回到上一個問題:*p3 不是什麼也沒做,而是改變了步進長度。
printf("p3:%p, p3+1:%p
", p3, p3+1);
printf("*p3:%p, *p3+1:%p
", *p3, *p3+1);
運行結果:
p3:0x7ffe3ecc88c0, p3+1:0x7ffe3ecc88c8
*p3:0x7ffe3ecc88c0, *p3+1:0x7ffe3ecc88c4
推薦閱讀: