學習C語言,指針絕對是一道大坎,很多人談指針色變,使用起來小心翼翼的。“一切指針都是紙老虎” ,同時,對我們得“在戰略上藐視指針,戰術上重視指針”。
本文先下,多維的情況後序博客繼續更新。
文章流程:
1、辨析指針和數組的不同
2、辨析它們相同的時刻
3、總結
首先說一點,指針的使用等同於數組的情況遠遠多於他們不同的情況,因此,在初學時,為了容易理解,很多人都。 但是,這卻的!
來個例子吧:
array[以上是在文件1中的定義
* array
以上是在文件2中的聲明
上面的例子對不對呢? 大家可以自己測試下,會很神奇的發現: 咔,怎麼編譯出啦! 呢?
在辨析數組和指針前,首先要說下聲明和定義的區別,之前博文“為何不精通C? 03 深入剖析聲明” 中的末尾已經提過這一點了。這裡重新說下:
C語言中,對象,而聲明卻可以有。
定義:只能出現在一個地方,確定同時分配內存,它是特殊的聲明
聲明:只是其他地方創建對象的。有extern前綴,作用於變量
對於,就像斷言一樣,,因為在聲明的同時,也規定了指針/數組的移動方式及長度。
So, 對於上面的例子,我們可以知道,file2.c中,array被聲明成一個int指針。但是,file1.c 中的定義卻是數組。 他們不兼容! 呢?
這裡先補充一個知識點,sizeof(x) 這個運算符,它返回的是x在內存中的字節數。
#include array[ printf( printf(,,(), (* printf(,,(), (* printf(,,(), (* printf(,,(), (* printf(,,(), (* printf(,,(), (* }
這裡,我們可以歸納出,所有的, 都是4字節(因為我的電腦是32位=4*8bit。同理,在64位電腦這裡顯示8)。
我們認真觀察下,sizeof(array), sizeof(&array[0]),(因為我們都說數組名就是首地址指針,所以我這麼表示。)
可以看出,打印出了80, 即20*4,20個int的字節長度。但是,還是4,指針的固定長度。喏,一大區別就在這!
好,通過sizeof, 能夠很好認識到原來數組和指針還真存在著不同點。現在繼續說下通過。
由sizeof可以知道,在定義數組時,等同於在內存中連續分配了N長度的空間,數組的首地址(假設是5000)代表這段空間的起始點。比如通過array[i]訪問時,步驟如下:
而通過指針呢? 我們都只是指針中保存的是地址值, 如 int*p = array; 這裡,假設p的地址為6000, 它存的值為array的首地址5000, 通過 p[i]訪問是,步驟如下:
可以看出,多了一個步驟。這個多出來的步驟,其實大家都知道,這也說明了指針的靈活性。
關於字符數組,我們可以這麼來初始化:
*p = a[] = ;
我們來辨析下內部隱含的區別吧:
對於指針p, 系統為我們分配了匿名一個,這個常量是的,把它的地址給了p, 因此字符串常量的值。
對於數組a, 系統定義了一個連續的內存塊來分配字符串,它的首地址是a, 我們操作來修改某個字符的值。
在C語言中,數組的首地址被定義為“不可修改的左值”, 即類似 int * const a 這樣的聲明, 我們可以通過它修改它指向的內容,卻不能把它賦個新值。即:允許a[i]=yyy,而對 a=xxx 卻是提示非法的!
指針呢,就看他怎麼聲明咯, 一般來說,就是 int* p, 我們可以 p=a, p=xxx, p[i]=yyy ……,都是允許的。
好啦,大概的區別點就是上述表示的了,那我們繼續探討下他們什麼時候相同。
我們知道,指針充滿了靈活性,而數組卻是比較死板的東西,這麼說來,就必須先理解好數組,才能更好的了解指針,我們先來說下數組。對於C語言來說,任何事物都必須聲明,再使用,我們也按這個順序,先說下聲明:
2、C語言將數組下標作為指針的偏移量
3、,即:
my_func(* p[]);
都是一個意思,編譯器都把它翻譯成指針。
采用《C專家編程》中的總結,我適當修改合並了一些。作者建議我們在自己真正理解數組、指針後,要先自我總結下,再看他的總結。
1、用 a[i]形式的表達式,編譯器都解釋成*(a+i);
2、指針永遠是指針,不可改寫成數組。你可以通過下標形式訪問指針,且必須是你知道指針指向了是一個數組。 畢竟,編譯器並不知道 int*指向了什麼,一個int數組還是int變量地址。
3、作為函數參數時,數組都被改寫成指針的形式來表達,即類似於 p=&a[0];因此,對於編譯器而言,參數表中沒有數組,只有指針。
4、聲明和定義必須匹配!若是定義了數組,在其他文件聲明時也必須是數組,指針亦然。