<C和指針---讀書筆記6>
指針
指針是一種變量,和int、float、char一樣,是一種基本的變量。只不過它比較抽象一些。
我們知道在C語言中,聲明一個變量a、b,編譯器會為其分配一個物理地址 addr_1 、addr_2,在之後的C語言中,a =1操作,是把數值1存入該 addr_1,就等價於a值變為1。b = b+1 ,是先讀取 addr_2的內容,加1操作後,再寫會 addr_2內。
可以這樣理解: 變量出現在 =右側,一般是 讀 addr_x的內容,變量是左值,一般是 存入 addr_x。 在C語言中變量實質上就是 物理地址的代號。對變量名的操作本質上就是對 物理地址的操作。
所以 a =1 ,b=b+1,都無非是 地址的讀寫操作。 像float、int、char這類變量,變量名等價於物理地址,a = "address 1" b= "address 2"
訪問a就是訪問 address1. address1/2裏面的內容就是a、b的值,沒有其他特別的意義。
int *p 聲明了一個指針變量p, 依然存在 p = "address 3" 的映射。但是p裏面的內容是一個特別得信息。它是地址 "address n“。
C語言使用 *p 間接的訪問 ”address n“ 使用p訪問 "address 3",
聲明和初始化
(1) int *p ; p = &a (2) float *p = &b ;
方法1,首先聲明p是一個 "指向int"的指針變量。 然後 p = &a ,把a的地址,存入 p內。 即 p內存儲的值 = address_a
方法2, 聲明p是一個 "指向float"的指針變量。 是一個縮寫形式。
一定要理解: 變量p自己有一個物理地址addr_p,只不過(addr_p) = &a.
未初始化和非法指針
因為我們經常需要對 指針變量進行間接訪問,一定要保證指向的地址是一個安全可靠的。比如指針變量指向了一個未知的地址,後續盲目的
對該地址進行間接讀寫,很可能出現大問題。所以要保證指針--->安全地址。
非常可惜的是: 編譯器對於未明確指定的指針變量不會進行分配。那我們分配到哪?最好有一個 絕對安全的地址供我們使用。
NULL指針: NULL值在stdio.h文件有明確 #define NULL ( (void *) 0 ) 把整型0強制轉為指針型,並指向void類型數據。
int *p = NULL ; int *p = (void *) 0 相當於 指針變量p = 0,並指向了 void。
指針變量的間接訪問 和直接訪問
int *p = &a ; 這時候 p = 10 ;這是非法的,本質原因是: 10是整型變量,p是 指針型變量,不能對等。 可以 p = (int *) 10; 把10也變為
指向整數的指針變量。
&p: 同樣對變量p取地址,獲得的是p的物理地址。該操作合情合法。
*p : 左值,表示存入 (P)----> address 內。 右值,取(P)----> address內的數據。
* &a = 25 , 即 * (address a) = 25 即存入 a地址內。
指針的指針
既然指針是一個變量,自己擁有自己的地址,那完全可以再用指針指向它,。 這就是指向指針的指針,簡稱指針的指針
怎麽聲明? int **pp ;
怎麽表明指向的規則? int *p = &a ; int **pp = &p 即可。
那麽如何通過指針的指針 訪問 整型變量a?
pp = &p
*pp 是對 指針變量p的間接操作。 *p 是完成對 整型a的間接訪問。
**pp 才是最終對a的間接訪問。
指針表達式實例
Char ch =’a’;
Char *cp = &ch;
表達式形式 |
左值 |
右值 |
&ch |
|
獲得ch變量的地址 |
cp |
修改cp的內容,則指向位置將會變化 |
讀取cp的內容,即獲得某個間接地址 |
&cp |
|
獲得指針變量cp自己的地址 |
*cp |
把數據存入 間接地址內 |
獲取 間接地址 的內容 |
*cp+1 |
非法 |
獲取 間接地址 的內容,並加1操作 |
*(cp+1) |
把數據存入 (間接地址+1)內 |
獲取 (間接地址+1) 的內容, |
++cp |
非法 |
Cp值加1,再返回新cp值, 同時 指針的指向位置變化 |
Cp++ |
|
Cp值加1,返回舊cp值 同時 指針的指向位置變化 |
*++cp |
把數據存入(間接地址+1)內, 同時 指針的指向位置變化 |
獲取 (間接地址+1) 的內容, 同時 指針的指向位置變化 |
*cp++ |
因為返回的是舊cp值,故而 把數據存入(間接地址)內, 同時指針的指向位置變化 |
因為返回的是舊cp值,故而 獲取 間接地址 的內容 同時,指針的指向位置變化 |
++*cp |
|
獲取 間接地址 的內容,+1之後,返回值 指針的指向位置不會變化 |
(*cp)++ |
|
獲取 間接地址 的內容,並返回。 指針的指向位置不會變化 |
++*cp++ |
|
獲得間接地址 的內容+1,並返回 指針的指向位置變化 |
++*++cp |
|
獲得 間接地址+1 的內容,並對其加1,再返回, 指針的指向位置變化 |
這只是一個表格,描述了各種運算的結果。只為加深理解。
指針的運算
指針變量主要用於 間接操作,一般對指針變量本身的操作,並不是很多,主要就是加法運算。
float a[10] ;
float *p = a;
定義了一組浮點型數組,並把數組首地址賦給p。我們知道一個float 型會占用 4 bytes空間。
P = Address_of_a[0]. 如果我們執行p+1,本質上是想 P = Address_of_a[1]. 那麽p+1 應該是 p + 1* sizeof(float)
慶幸的是,C編譯器為我們進行了這個處理,使得我們可以更加方便的使用指針變量+1.
這也是我們聲明指針時,為什麽要說明指針指向的是什麽數據類型。它其實是為了編譯器處理 sizeof(xxx)操作、
<C和指針---讀書筆記6>