【c語言】帶你真正走進指標的世界——陣列與指標的關係(一)
每天下課之後,都感覺老師上課在神仙程式設計,我們一群凡人在底下面無表情地走神,前一秒還是在講加減乘除的基本用法,後一秒就變成了指標陣列、陣列指標、結構體指標和N級指標的性質以及運用............(真是令人頭禿 —^—)
————————————————下面是正文——————————————————
一.N級指標
(1). 一級指標
一級指標是我們最經常使用的指標,它的定義簡單明瞭——> 型別* 變數名
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*p1);
return 0;
}
編譯結果毫無新意
然後再看下彙編
結果就是毫無新意的取出p1所存的地址中的值而已~那麼如果我把程式碼修改成這樣,結果還會一樣嗎?
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*(p1+0));
return 0;
}
彙編如下
嗯......在彙編的角度來看和直接寫*p1是完全一樣的,那編譯結果不出意料的話應該也是一樣的
如果這樣的話,按照我對彙編的理解,突然想到了這樣的一種修改方法
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",p1[0]);
return 0;
}
檢視一下結果
答案是出其地一致的,但是彙編會不會是不一致的呢???
答案是:它們三個彙編是一樣的。這個時候,我們可不可以得出這樣一個結論呢?
*(P+ i)= P [ i ]
我們嘗試一下程式碼
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*(p1+1));
printf("%d\n",p1[1]);
printf("\n");
printf("%d\n",*(p1+2));
printf("%d\n",p1[2]);
return 0;
}
結果如下:
得到的結果也是完全一致的,所以,我們可以得出第一個結論:在一級指標中,*(P+ i)= P [ i ]
(2). 二級指標
加一顆 ” * “ 就能成為一級指標,那麼兩顆 ” * “ 就是傳說中的二級指標了。二級指標其實就是我們俗稱的 “ 指標的指標” ,很多書上或者網上都故作玄虛地擺弄著術語說
嗯......感覺這些人寫這些東西就是想混餚我的思路,故意不讓我聽明白的樣子......其實二級指標可以這樣理解!
int x = 100;
int* p1 = &x;
p1是個變數名,它的型別為int* ,它裡面儲存的是 x 的地址。over。
int x = 100;
int* p1 = &x;
int** p2 = &p1;
p2是個變數名,它的型別為int**,它裡面儲存的是 p1 的地址。over。
那我可不可以這樣寫呢?
int** p2 = &x;
編譯器告訴我們是不能的。
錯誤的原因是不能把一個型別為 int* 的值賦值給 int** ,也就是我在文章開頭給出的那個連線的部落格裡面提到過的 ”&x“ 是 int* 型別的,只能用同是 int* 型別的p1來接收,而”&p1“ 是int** 型別的,只能用型別是int**的p2來接收。
綜上所述,二級指標(指標的指標),就是用來儲存型別為兩顆” * “ 的值的容器。over。
接下來,我要放大招了!
根據一級指標中得出的一個結論:*(P+ i)= P [ i ] ,那在二級指標裡面,我們可不可以大膽地這樣來定義?
在二級指標中,*(*(P+ i)+j ) = P [ i ] [ j ]
我們寫出這樣的程式碼
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
printf("%d\n",*(*p2));
printf("%d\n",*(*(p2+0)+0));
printf("%d\n",p2[0][0]);
return 0;
}
編譯的結果如下
再看一眼彙編
也是完全一樣的,所以可以得出這樣的結論:在二級指標中,*(*(P+ i)+j ) = P [ i ] [ j ]
——————————————————小插曲————————————————————
有些同學不是很懂 *(*p2) 得出來的為什麼會是 100,這樣簡單地說一下:首先 (*p2 )得到的值是 p2所儲存的地址(就是p1 的地址) 所指向的東西 (就是 x 的地址),所以 (*P2) == x 的地址,然後 *(*p2) 得到的值是(*p2)所儲存的地址(就是x 的地址) 所指向的東西 (就是 100),所以 *(*P2) == 100
—————————————————————————————————————————
(3). 三級指標
換句話說,三級指標就是” 指標的指標的指標 “,不過經過上兩級的指標的 ”洗禮“,估計再怎麼複雜的指標,都不會再搞混定義了,所以在此不再累贅。三級指標的賦值也是和二級指標一樣,賦值號左右的型別需要同時相等才能賦值,所以
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
int*** p3 = &p2;
return 0;
}
然後我們再來把上兩級的套路套在三級指標上面
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
int** p2 = &p1;
int*** p3 = &p2;
printf("%d\n",*(*(*p3)));
printf("%d\n",*(*(*(p3+0)+0)+0));
printf("%d\n",p3[0][0][0]);
return 0;
}
發現編譯的結果
和彙編的過程
也是完全一樣的,所以,當我們在往下一直探索 N級指標時,我們可以總結出幾個這樣的結論:
1. *()與 【 】 是可以互相轉換的
2. *(P+I) = P [ I ]
*(* (P+I) + J ) = P[ I ] [ J ]
............