指針是學習C\C++的一個重難點,同時也是這個語言的關鍵知識點。如果不能夠對指針有著深刻的理解,會對學習C\C++有著極大的阻礙。 普通變數和指針變數的區別 普通變數和指針變數都同為變數。對於一個變數來說,都具有值和地址兩個屬性。假設一個普通變數a = 5,其值為5,&a為變數a在記憶體占有的地址。此 ...
指針是學習C\C++的一個重難點,同時也是這個語言的關鍵知識點。如果不能夠對指針有著深刻的理解,會對學習C\C++有著極大的阻礙。 普通變數和指針變數的區別 普通變數和指針變數都同為變數。對於一個變數來說,都具有值和地址兩個屬性。假設一個普通變數a = 5,其值為5,&a為變數a在記憶體占有的地址。此時定義一個指針變數,並將a的地址賦值給該指針變數,int *p = &a,此時p指向a的地址空間,即p的值為a的地址,*p為p指向a的地址空間的內容,此時*p = 5。而&p為指針p所在記憶體空間的地址,需要註意的是,雖然p指向a,但兩者在同一記憶體所占有的地址並不相同。 可見如下代碼:
1 //定義普通變數a和指針變數p 2 int main(){ 3 int a = 5; 4 int* p = &a; 5 printf("a = %d,&a = %d\n",a,&a); 6 printf("p = %d,*p = %d,&p = %d\n",p,*p,&p); 7 8 return 0; 9 }
運算結果如下:
多級指針 可先看如下代碼:
1 int a = 10; 2 int* p = &a; //一級指針 3 printf("a = %d, &a = %d\n", a, &a); //a的值,a的地址 4 printf("p = %d\n", p); //p等價於&a 5 printf("*p = %d\n", *p); //*p等價於a 6 7 int** q = &p; //二級指針 8 printf("q = %d\n", q); //q是指針q的地址 9 printf("*q = %d\n", *q); //*q等價於p 10 printf("**q = %d\n", **q); //**q等價於*p等價於a 11 12 int*** t = &q; //三級指針 13 printf("t = %d\n", t); //t是指針t的指針 14 printf("*t = %d\n", *t); //*t等價於q 15 printf("**t = %d\n", **t); //**t等價於*q等價於p 16 printf("***t = %d\n", ***t); //***t等價於**q等價於*p等價於a
運算結果如下:
看到這,想必對於任何一名C語言初學者來說,都會感到十分的疑惑——僅僅只是對“*”這麼一個符號的增增減減,卻能夠得到不一樣的結果。那麼在不使用電腦的情況下,我們到底該怎麼區分一級指針、二級指針甚至是多級指針呢?在這裡我們就得引入一個非常重要的概念——記憶體。 記憶體 記憶體是電腦組成中,用來暫存程式和數據,輔助CPU運算的一個重要的部分,可以說記憶體是CPU與硬碟溝通的橋梁。它能夠暫存CPU的運算數據,也可以暫存與硬碟等外部設備交換的數據。在下圖中,我們可以很清楚的看到,記憶體在整個電腦系統中起到的關鍵性的作用(主存儲器指記憶體)。
申明任何一個變數,都會在已分配的記憶體中,開闢出一塊空間,根據不同的變數類型,開闢出的空間大小和形式是不一樣的,比如說int型的變數,會在記憶體中開闢出一個4個位元組的空間,char型的變數,會在記憶體中開闢出一個1個位元組的空間;而對於申明一個整型數組,如int a[10],則會在記憶體中開闢出一塊4*10個位元組且連續的空間。對於指針變數,它會指向變數對應的地址,那麼這個地址到底該如何規定,這就得引入另一個概念——記憶體地址 記憶體地址 電腦會對記憶體的每一個位元組分配一個32位或64位的編號,(這與32位或者64位處理器相關),這些記憶體編號我們稱之為記憶體地址。對於初學者,我們可以將記憶體抽象成一個很大的一維字元數組,每個單元都有其唯一的ID,這個ID就可以理解為記憶體地址。可見下圖。
下麵回歸到多級指針,在瞭解到上述知識後,可對多級指針有了一個大致的理解。我們將申明的多個變數抽象到下圖中。
指針變數t的值是它在記憶體的相對地址,*t 等價於q,**t 等價於p,***t 等價於a,同理,指針變數q的值是它在記憶體的相對地址,*q 等價於p,**q等價於a。通過這種方式,我們可以很清晰明瞭地理解多級指針。