C語言事實上不簡單:數組與指針
之前在寫C的時候,沒怎麽留意數組。就這麽定義一個。然後顛來倒去的使用即可了。只是後來碰到了點問題。解決後決定寫這麽一篇博客,數組離不開指針。索性就放一起好了。
如今我定義了一個數組:int cc[10];
環繞這個數組有好幾種指針:cc, cc+1, &cc[0], &cc, &cc+1等等。你知道它們都是什麽含義嗎?試試執行下面帶代碼:
#include <stdio.h> int main() { int cc[10]; printf("%x\n", cc); printf("%x\n", cc+1); printf("%x\n", &cc[0]); printf("%x\n", &cc); printf("%x\n", &cc+1); getchar(); return 0; }
cc+1,這是指向數字第二個位置的指針。
&cc[0],這個事實上就是cc,指向數組的首個元素。
&cc。這是什麽玩意兒?指向指針的指針?
&cc+1,假設上面的意思是指向指針的指針。那這個豈不是指向野地址了?
如果執行環境是32位機。而且數組首地址為0x28ff00。那麽:
cc的結果為0x28ff00,這點毫無疑問。
cc+1的地址是0x28ff04而不是0x28ff01,由於一個int占用了4個字節的空間。cc+1事實上是當成cc+1*sizeof(int)來看待。
&cc[0]的結果是0x28ff00,cc[0]表示的是數組的首個元素。那麽&cc[0]自然就是首個元素的地址了。&cc[0] == cc。
&cc,這個就難說了。指針cc的值是0x28ff00,&cc表示這個指針本身的地址,我們怎麽可能會知道這個地址?輸出是個隨機地址嗎?隨機數的話這個輸出全然沒有意義啊。假設不是隨機地址的話,難不成還是0x28ff00?這種話a不就等於&a了?明顯不正確吧。
。
。
對於基本類型的指針,如int *tt; 那麽*tt是其值,&tt是指針的地址,&tt != tt
可是上述的cc是個數組。實際上。&cc被編譯成了&cc[0],可是其含義不同,&cc指向的是整個數組的開頭。
&cc與cc的指向能夠用下圖來形象表示:
上圖能夠看出,&cc事實上代表的是int(*)[10],那麽&cc+1就能夠理解為cc + sizeof(cc)/4,之所以除以4是由於int型指針++事實上是移動了4個字節。
又或者說%cc == cc + sizeof(cc)/4 == cc + 10。所以&cc+1的值為0x28ff28。
可見我們尋常使用的數組名,並不能單純的當成指針看待。數組名的本質是代表數組對象的變量名,是一個左值,是一個不能被改變的左值。
可是因為在程序中不保存數組的大小,所以通過數組名僅僅能訪問數組的左值。不能訪問數組的右值。
因為這個原因,數組名在作為右值使用的時候被賦予另外一個新的意義——指向數組第一個元素的指針。這就是array-to-pointer轉換規則。
依據標準規定。僅僅有當數組名作為sizeof、&運算符的操作數的時候。它是一個左值,其類型為數組類型。除此之外的全部情況,數組名都是一個右值,被編譯器自己主動轉換為指針類型,這樣的情況下我們就說數組名是一個指針。而且是一個指針常量。
接下來是另外一些有趣的東西,我們結合sizeof與數組輸出各類值。
下面程序的輸出結果是什麽?建議思考後再執行程序來驗證答案。
#include <stdio.h> int main() { int cc[10]; printf("%d\n", sizeof(cc[0])); printf("%d\n", sizeof(cc)); printf("%d\n", sizeof(&cc)); printf("%d\n", sizeof(int(*)[10])); getchar(); return 0; }sizeof(cc[0]),一個int的大小。輸出4,沒問題。
sizeof(cc),註意不要和上面搞混。這不是數組首地址的指針,cc在這裏是左值。其為數組類型。所以結果為40。
sizeof(&cc),這個的答案應該是多少呢?註意了。cc在這裏還是左值,其為數組類型,但&cc不同於cc,無論數組怎麽復雜它始終是個指針,32位機上指針大小始終是4個字節。所以結果為4。
sizeof(int(*)[10]),這個事實上和上面的&cc是一個樣的,代表了整個數組,但還是指針,所以結果相同為4。
練習:以下的程序輸出結果是什麽(如果32位機):
#include <stdio.h> int main() { int *p[2]; printf("%d\n", *p); printf("%d\n", sizeof(p)); printf("%d\n", sizeof(&p)); getchar(); return 0; }
答案是:隨機數、8、4
再來一個練習:下列程序的輸出是什麽?
#include <stdio.h> int main() { char str[]="hactrox"; char *p = str; printf("%d %d\n", sizeof(str), sizeof(p)); getchar(); return 0; }
答案:8、4(不要忘了‘\0‘)
C語言事實上不簡單:數組與指針