相信不少的C語言初學者都知道,數組名相當於指針,指向數組的首地址,而函數名相當於函數指針,指向函數的入口地址。現在又這樣一個問題,如果對數組名取地址,那得到的會是什么呢?很多人立刻會想到:給指針取地址,就是指針的指針,既二級指針嘛!當然這樣的結論是錯誤的,不然這篇筆記也就沒有意義了。
下面我們來逐步分析,下面是一段驗證這個問題的代碼
- #include<stdio.h>
- int main()
- {
- int a[10];
- printf("a:/t%p/n", a);
- printf("&a:/t%p/n", &a);
- printf("a+1:/t%p/n", a+1);
- printf("&a+1:/t%p/n", &a+1);
- return 0;
- }
大家可以編譯運行一下,我的輸出的結果是:
- /*
- a: 0012FF20
- &a: 0012FF20
- a+1: 0012FF24
- &a+1: 0012FF48
- */
a和&a指向的是同一塊地址,但他們+1后的效果不同,a+1是一個元素的內存大小(增加4),而&a+1增加的是整個數組的內存大小(增加40)。既a和&a的指向和&a[0]是相同的,但性質不同!
讀到這里,有很多朋友已經明白其中的機制了,如果還是有些模糊,請繼續往下看
- int main()
- {
- int a[10];
- printf("%d/n",sizeof(a));
- return 0;
- }
這段代碼會輸出整個數組的內存大小,而不是首元素的大小,由此我們是否聯系到,sizeof(a)這里的a和
&a有些相同之處呢?! 是的,沒錯,&a取都得是整個數組的地址!既數組名取地址等價於對數組取地址。
好了,讓我們總結一下,如果你還是不太理解,不用擔心,下面的概念很清晰
其實a和 &a結果都是數組的首地址,但他們的類型是不一樣。
a表示&a[0],也即對數組首元素取地址,a+1表示首地址+sizeof(元素類型)。
&a雖然值為數組首元素地址,但類型為:類型 (*)[數組元素個數],所以&a+1大小為:首地址+sizeof(a)。
還有這篇文章最初提到的指針的指針的那個錯誤結論,其實即使不懂上述內容,也應該判斷出結論是錯誤的,大家應該在了解數組名即是數組的首地址的同時,也要知道,數組名僅僅是“相當”於指針,而並非真的是指針,數組名是只是個常量(一個值為數組首元素地址的常量),所以不能進行++或者--運算。而常量更是無法取地址的,而之所以有&a,其實這里的a的意義早已經不是當初那個數組名了,它此時代表了整個數組。
結論2:數組作為左值和數組作為右值時的區別造成了無數人的困惑與誤解:foo 作為右值時確實等價於一個指針,因為數組無法像普通對象那樣返回它的值,它的元素可能有成百上千個,但作為一個左值時——比如作為取地址操作符的操作數時,數組就是作為一個數組對象而出現的,而不是指針,取地址返回一個指向數組的指針,而不是指向指針的指針。
一句話總結就是:數組就是數組,有着自己的特性。
(題外話:從生成的匯編語言看,用指針來訪問內存實際上並不比使用數組來訪問內存快,反而是慢了)
轉載請注明來源 http://blog.csdn.net/imred/article/details/45441457