透徹理解指針

     看到很多初學者對指針不是很理解,很多書籍對指針長篇大論,筆者就自己的理解寫一下指針的概念,希望對大家有所幫助,如有錯誤,歡迎指正~~

一,背景知識

    從軟件角度看,計算機的內存是一個一個整齊排放的小格子,每個格子中可以存儲數據內容,每個格子都有地址。

    變量是對一個或多個內存小格子中內容的解釋。

二、指針概念

    int型變量在32位機器上佔4個字節(四個內存小格子),用於存儲整數。

    指針就是一個變量,在32位機器上佔用4個字節(64位機器上佔用8個字節),用於存儲內存地址,指針和普通變量沒有區別。要說區別,那就是其存儲的內容可以解釋爲整形數的地址,浮點數的地址,函數的地址,數組的地址等等。

    取地址:

int *p = &i;

    將i變量的內存地址放入,p指針變量的內存單元中。對內存單元以int的方式解析,也就是4個單元格爲一組。

    解引用:

int i = *p;

    p指針變量內存單元中存儲了一個內存地址,到這個地址所在的內存將數據取出來放入i變量中。對指針解引用一定考慮內存是否還在,以什麼類型解析。

    到這裏,如果從內存的角度理解了變量,應該就能完全理解指針了,下面只是一些例子而已

三、指針與數組

    指針和數組都是基本變量,數組是內置變量,而不是類似結構體定義出來的複合變量。

    本來數組和指針也沒多大關係,但很多人認爲他們是一樣的,等價的,這裏從自己的角度簡單說一下自己的理解。

int *p  = "1234";
int a[] = "1234";

p和a的內存模型是不一樣的,如下圖所示:

    

                                圖1 指針p的內存模型                                                    圖2 數組a的內存模型

很明顯在這裏p是對一段內存的間接引用,數組a就是指一段內存。兩者的區別,做一個類別就很清晰了:

int a = 0x12345;
char *p = (char*)&a;

     這段代碼的內存模型和上面的內存模型是幾乎一樣的,你可以把數組類比爲int類型,認爲它是char類型數據的一個數組。再強調一遍數組是內置數據類型和int,char等是一樣的。

    當然,你可能會說當數組做函數參數的時候,它就是指針呀,沒錯,這是編譯器的一個優化。

    函數參數是什麼?是給函數使用的一個局部變量。數組當函數參數,按理說應該創建一個數組局部變量,並將內容拷貝過來,給函數內部使用,但是複製一個數組變量效率很差,所以直接創建一個指針指向原來的數組內存就快速的多了。

    有句話“數組名是指向數組的const指針”,這句話也好理解,對int a,a就是指向它佔用的4個內存格子中第一個格子的地址。

四、指針與函數

    其實沒什麼好說的,就理解下面兩句代碼吧,

int* func1 (int a, int b){}
int (*func2)(int a, int b);

   首先說一下指針的類型,其實一開始就說了,這些char *pa,int *pb, void *pc 變量在內存中是一樣的,可以隨意類型轉換,但是轉換之後,其內存中內容的解析方式就不一樣了,pa是去其內存值得地址處取一個內存格子的東西,pb是去其內存值得地址處取4個格子的東西,pc是不知道咋取東西,解引用時需要類型轉換。

   還要說一下c語言的語義解析方式,一般是從左向右,就以上邊兩條代碼來說func1向右是左括號,很明顯就是一個函數了,func2向右是右括號,然後再看左邊是*,很明顯就是指針了。(這部分詳細瞭解可看《C專家編程》)

   func2是一個簡單的指針變量,對它的解釋就是按函數func1的方式進行解析。

五、結束語

    對語義的理解,最簡單最直接的理解還是以內存模型(也就是小格子)爲基礎,畫出了內存模型,無論是什麼類型的指針還是幾階指針都一目瞭然了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章