當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > C語言——指針
指針:也可以叫指針變量,與其他類型的變量相同,同樣保存一個(gè)值,只不過保存的值是一片地址(16進(jìn)制數(shù))
注:在32位機(jī)上,指針統(tǒng)一占4個(gè)字節(jié),64位機(jī)則占用8個(gè)字節(jié),因?yàn)橹羔樉褪怯脕肀4?span id="t1955575tlb" class="Apple-tab-span" style="white-space:pre"> 地址,所以地址多大,指針就有多大。
一、使用指針需要了解并注意:
因?yàn)橹羔樣涗浀氖堑刂,所以理論上來說,指針就記錄了一個(gè)16進(jìn)制數(shù),所以以下操作是合理:
int *p = 0xFFFF10;
但是編譯器會(huì)報(bào)警告,警告的原因是p需要接受一個(gè)int *類型的數(shù)據(jù),而0xFFFF10是一個(gè)立即數(shù),不知道是什么類型的,于是為了騙編譯器,所以可以修改代碼為:
int *p = (int *)0xFFFF10; //強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換
編譯和運(yùn)行以上代碼會(huì)發(fā)現(xiàn),程序不會(huì)有任何錯(cuò)誤,這是因?yàn)橄到y(tǒng)允許指針記錄任意的地址值,但是對于該指針不要進(jìn)行讀寫操作,因?yàn)橹羔樦赶虻膬?nèi)存,當(dāng)前進(jìn)程是否有權(quán)限操作是不確定的,如果沒有權(quán)限操作程序會(huì)報(bào)段錯(cuò)誤
二、指針的作用:
1.可以間接訪問,提高效率
2.函數(shù)傳參時(shí)直接傳地址,更方便,地址傳遞最大的好處是節(jié)約內(nèi)存開銷
3.可以使用堆空間,獲取更大的內(nèi)存操作空間
1:直接訪問與間接訪問
直接訪問:直接訪問一個(gè)變量名,是訪問的內(nèi)存空間中的值通過變量名做賦值操作,是可以直接修改內(nèi)存空間中的值。在內(nèi)存中尋找這個(gè)名字的變量,速度慢,效率低。
間接訪問:通過記錄某個(gè)變量的內(nèi)存地址(通過指針變量來進(jìn)行保存記錄),通過訪問該指針可以獲取到其內(nèi)存地址,也可以通過對該指針進(jìn)行取值操作,獲取到指針指向內(nèi)存空間中的值。直接通過地址找到這個(gè)變量,速度快,效率高。
2:函數(shù)傳參
值傳遞:對于一些簡單的int或者char變量來說,我們直接采用值傳遞更方便
地址傳遞:如果要傳一個(gè)數(shù)組,值傳遞就會(huì)很麻煩。再如果需要一個(gè)函數(shù)指針,那么值 傳遞就很難實(shí)現(xiàn),所以這個(gè)時(shí)候我們就需要傳遞一片地址過去,功能函數(shù)直 接對這片空間地址中的數(shù)據(jù)進(jìn)行處理就可以了。
3:使用堆空間
棧:由系統(tǒng)管理的一塊內(nèi)存空間,由系統(tǒng)負(fù)責(zé)分配和釋放內(nèi)存,該內(nèi)存是可讀可寫的。 但是這片空間比較小,如果代碼中數(shù)據(jù)過大,可能導(dǎo)致棧不夠用。
堆:由用戶(開發(fā)人員)進(jìn)行管理的一塊內(nèi)存空間,由用戶調(diào)用系統(tǒng)調(diào)用進(jìn)行分配和釋 放內(nèi)存空間,是一塊可讀可寫的自由空間。這塊空間很大,一般來說已經(jīng)足夠我們 開發(fā)使用。而且使用堆空間,用鏈表操作數(shù)據(jù),比在棧上使用數(shù)組更容易增刪改查, 并且我們可以合理的開辟空間的大小,基本不會(huì)造成資源不夠或者資源浪費(fèi)。
三:指針的大小與萬能指針
指針的大小:因?yàn)橹羔樣涗浀氖堑刂罚缘刂氛级嗌賯(gè)字節(jié),那么指針的大小也就是多少,比如64位機(jī),指針占用8個(gè)字節(jié),
講道理,8個(gè)字節(jié)足以保存任意的變量地址。保存是肯定可以保存的,但是在對該指針取值或者賦值的時(shí)候就會(huì)出現(xiàn)問題
int a=10;-----------1010
char *p=&a;
所以我們可以得出結(jié)論,任意數(shù)據(jù)類型的指針,都可以保存任意類型數(shù)據(jù)的變量的地址,
但指針的數(shù)據(jù)類型,是在限制對指針操作時(shí),要從指向內(nèi)存中獲取多少字節(jié)的數(shù)據(jù),即指針的數(shù)據(jù)類型就是為了在對指針取值時(shí)使用的
所以建議:什么類型的變量的地址,就使用什么類型的指針去指向
由此就可以引出我們的一個(gè)空指針類型,也就是萬能指針:void *
這個(gè)叫做空指針類型,也稱之萬能指針,萬能指針可以保存任意類型變量的地址,也可以將萬能指針保存的地址值,賦值給任意類型的指針變量
但是要注意:萬能指針,同樣不能做取值的操作,因?yàn)椴恢廊《嗌僮止?jié)的數(shù)據(jù)
四:空指針和野指針
野指針:指向不明確,或者是說指向的內(nèi)存是否有權(quán)限訪問不明確,這樣的指針稱之為野指針,如果對一個(gè)野指針進(jìn)行取值等操作,出錯(cuò)也正常,不出錯(cuò)也正常
空指針:指針定義出來后賦值為NULL,則說該指針為空指針
NULL是一個(gè)宏,該宏被define為(void *)0x0
在linux中規(guī)定0號(hào)內(nèi)存默認(rèn)不分配給任意進(jìn)程使用,是一塊不可讀也不可寫的內(nèi)存,如果你不小心操作了該指針,絕對會(huì)出錯(cuò)(段錯(cuò)誤)
所以建議:當(dāng)定義一個(gè)指針時(shí),此時(shí)不知道指針要賦什么值的時(shí)候,建議初始化為NULL(int *p=NULL;)
五:指針的運(yùn)算
*:取值運(yùn)算
&:取地址運(yùn)算
++:指針進(jìn)行++操作,并不是在其地址值上+1,而是做地址偏移
至于地址要偏移多少,取決于指針的數(shù)據(jù)類型,如果是int類型的指針,偏移4個(gè)字節(jié),如果是char型,偏移1個(gè)字節(jié)
六:多級(jí)指針
多級(jí)指針:
一級(jí)指針可以指向變量的內(nèi)存,二級(jí)指針記錄一級(jí)指針的地址,三級(jí)記錄二級(jí)地址,以此類推
二級(jí)指針有權(quán)利去讀取一級(jí)指針的值,或修改一級(jí)指針的指向
七:const修飾的指針(指針常量與常量指針)
常量與指針:
常量指針:是一個(gè)指針,指針指向一塊"常量"空間,指針指向(值)可以發(fā)生更改,但指針指向空間的值不允許修改
語法:const 數(shù)據(jù)類型*指針名稱 or 數(shù)據(jù)類型 const *指針名稱
例如:const int *p or int const *p;
指針常量:是一個(gè)常量,指針的指向(值)不可以發(fā)生更改,但指針指向空間的值允許修改
語法:數(shù)據(jù)類型 *const 常量名稱
例如:int *const p;
常量指針常量:是一個(gè)指針,但是一個(gè)常量指針,指針指向(值)不可以發(fā)生更改,指針指向空間的值也不允許修改
語法:const 數(shù)據(jù)類型 *const 指向名稱;
例如:const int *const p;
如果函數(shù)需要一個(gè)常量指針,實(shí)際是間接在提示調(diào)用者,該參數(shù)你可以放心傳參,因?yàn)槭褂玫闹羔槢]有權(quán)限去修改你內(nèi)存的值
八:指針的用法與圖解