C語言——指針
時間:2019-08-06 來源:深圳中心,杜老師
指針:也可以叫指針變量,與其他類型的變量相同,同樣保存一個值,只不過保存的值是一片地址(16進制數)
注:在32位機上,指針統一占4個字節,64位機則占用8個字節,因為指針就是用來保存 地址,所以地址多大,指針就有多大。
一、使用指針需要了解并注意:
因為指針記錄的是地址,所以理論上來說,指針就記錄了一個16進制數,所以以下操作是合理:
int *p = 0xFFFF10;
但是編譯器會報警告,警告的原因是p需要接受一個int *類型的數據,而0xFFFF10是一個立即數,不知道是什么類型的,于是為了騙編譯器,所以可以修改代碼為:
int *p = (int *)0xFFFF10; //強制數據類型轉換
編譯和運行以上代碼會發現,程序不會有任何錯誤,這是因為系統允許指針記錄任意的地址值,但是對于該指針不要進行讀寫操作,因為指針指向的內存,當前進程是否有權限操作是不確定的,如果沒有權限操作程序會報段錯誤
二、指針的作用:
1.可以間接訪問,提高效率
2.函數傳參時直接傳地址,更方便,地址傳遞最大的好處是節約內存開銷
3.可以使用堆空間,獲取更大的內存操作空間
1:直接訪問與間接訪問
直接訪問:直接訪問一個變量名,是訪問的內存空間中的值通過變量名做賦值操作,是可以直接修改內存空間中的值。在內存中尋找這個名字的變量,速度慢,效率低。
間接訪問:通過記錄某個變量的內存地址(通過指針變量來進行保存記錄),通過訪問該指針可以獲取到其內存地址,也可以通過對該指針進行取值操作,獲取到指針指向內存空間中的值。直接通過地址找到這個變量,速度快,效率高。
2:函數傳參
值傳遞:對于一些簡單的int或者char變量來說,我們直接采用值傳遞更方便
地址傳遞:如果要傳一個數組,值傳遞就會很麻煩。再如果需要一個函數指針,那么值 傳遞就很難實現,所以這個時候我們就需要傳遞一片地址過去,功能函數直 接對這片空間地址中的數據進行處理就可以了。
3:使用堆空間
棧:由系統管理的一塊內存空間,由系統負責分配和釋放內存,該內存是可讀可寫的。 但是這片空間比較小,如果代碼中數據過大,可能導致棧不夠用。
堆:由用戶(開發人員)進行管理的一塊內存空間,由用戶調用系統調用進行分配和釋 放內存空間,是一塊可讀可寫的自由空間。這塊空間很大,一般來說已經足夠我們 開發使用。而且使用堆空間,用鏈表操作數據,比在棧上使用數組更容易增刪改查, 并且我們可以合理的開辟空間的大小,基本不會造成資源不夠或者資源浪費。
三:指針的大小與萬能指針
指針的大小:因為指針記錄的是地址,所以地址占多少個字節,那么指針的大小也就是多少,比如64位機,指針占用8個字節,
講道理,8個字節足以保存任意的變量地址。保存是肯定可以保存的,但是在對該指針取值或者賦值的時候就會出現問題
int a=10;-----------1010
char *p=&a;
所以我們可以得出結論,任意數據類型的指針,都可以保存任意類型數據的變量的地址,
但指針的數據類型,是在限制對指針操作時,要從指向內存中獲取多少字節的數據,即指針的數據類型就是為了在對指針取值時使用的
所以建議:什么類型的變量的地址,就使用什么類型的指針去指向
由此就可以引出我們的一個空指針類型,也就是萬能指針:void *
這個叫做空指針類型,也稱之萬能指針,萬能指針可以保存任意類型變量的地址,也可以將萬能指針保存的地址值,賦值給任意類型的指針變量
但是要注意:萬能指針,同樣不能做取值的操作,因為不知道取多少字節的數據
四:空指針和野指針
野指針:指向不明確,或者是說指向的內存是否有權限訪問不明確,這樣的指針稱之為野指針,如果對一個野指針進行取值等操作,出錯也正常,不出錯也正常
空指針:指針定義出來后賦值為NULL,則說該指針為空指針
NULL是一個宏,該宏被define為(void *)0x0
在linux中規定0號內存默認不分配給任意進程使用,是一塊不可讀也不可寫的內存,如果你不小心操作了該指針,絕對會出錯(段錯誤)
所以建議:當定義一個指針時,此時不知道指針要賦什么值的時候,建議初始化為NULL(int *p=NULL;)
五:指針的運算
*:取值運算
&:取地址運算
++:指針進行++操作,并不是在其地址值上+1,而是做地址偏移
至于地址要偏移多少,取決于指針的數據類型,如果是int類型的指針,偏移4個字節,如果是char型,偏移1個字節
六:多級指針
多級指針:
一級指針可以指向變量的內存,二級指針記錄一級指針的地址,三級記錄二級地址,以此類推
二級指針有權利去讀取一級指針的值,或修改一級指針的指向
七:const修飾的指針(指針常量與常量指針)
常量與指針:
常量指針:是一個指針,指針指向一塊"常量"空間,指針指向(值)可以發生更改,但指針指向空間的值不允許修改
語法:const 數據類型*指針名稱 or 數據類型 const *指針名稱
例如:const int *p or int const *p;
指針常量:是一個常量,指針的指向(值)不可以發生更改,但指針指向空間的值允許修改
語法:數據類型 *const 常量名稱
例如:int *const p;
常量指針常量:是一個指針,但是一個常量指針,指針指向(值)不可以發生更改,指針指向空間的值也不允許修改
語法:const 數據類型 *const 指向名稱;
例如:const int *const p;
如果函數需要一個常量指針,實際是間接在提示調用者,該參數你可以放心傳參,因為使用的指針沒有權限去修改你內存的值
八:指針的用法與圖解


