指針定義:
指針是一種數據類型,使用它可以用來定義指針變量,指針變量中存儲的其實是整數,這種整數代表了內存的編號。
指針的使用:
1、函數之間相獨立,但有些時候需要共享變量。傳參是值傳遞全局變量容易命名沖突使用數組還需要傳遞長度命名空間是獨立的,但地址空間是同一個,所有指針可以解決這個問題。
2、由于函數之間傳參是值傳遞(內存拷貝),對于字節數比較多的變量,值傳遞效率較低,如果傳遞變量的地址只需要傳遞4|8字節。3、堆內存無法取名字,它不能像data、bss、stack讓變量名與內存建立聯系,只能使用指針記錄堆內存的地址來使用堆內存。
指針使用方法:
定義:類型* 變量名_p;1、指針變量與普通變量的用法有很大區別,建議在取名以p結尾加心區分。2、指針變量與普通變量一樣默認值是隨機的,一般初始為 NULL。3、指針的類型決定了它可以訪問多少個字節。4、一個*只能定義一個指針變量。int* p1,p2,p3; // 只有p1 是指針變量,p2,p3都是int類型變量int *p1,*p2,*p3; // p1 p2 p3都是指針變量
賦值:變量名_p = 地址;指向棧內存:int* p = #指向堆內存:int* p = malloc(4);
解引用:*p空指針變量中記錄的內存編號去訪問內存,該過程可能產生段錯誤,原因是里面存儲的內存編號是非法的。注意:訪問的字節數由指針變量的類型決定。練習1、實現一個變量交換函數,調用它對一個數組進行排序。void swap(int* p1,int* p2);練習2、實現個函數計算兩個整數的最大公約數,和最小公倍數,最大公約數用return返回,最小公倍數使用指針處理。3 6 33 6 6
要注意的問題:
空指針:值為NULL的指針變量叫空指針,如果進行解引用就會產生段錯誤。NULL也是一種錯誤標志,如果一個函數返回值是指針類型,當函數執行出錯返回值就是NULL。如何避免空指針帶來的段錯誤:使用來歷不明的指針前做一判斷。1、當函數的參數是指針,別人傳給你的就有可能是空指針。2、從函數獲取的返回值也可能是空指針。if(NULL == p)注意:NULL在絕大多數系統中是0,在個別系統中是1。野指針:指向不確定的內存空間。解引用野指針的后果:1、段錯誤2、臟數據3、一切正常野指針比空指針的危害更嚴重,因它無法判斷出來,而且可能是隱藏型的錯誤短時間內不暴露出來。所有的野指針都是程序員自己制造出來的,如何避免產生野指針:1、定義指針變量時一定初始化。2、函數不返回棧內存的地址。3、指針指向的內存釋放后,指針變量要及時置空。
指針運算:
指針變量中存儲的是整數,理論上整型數據可以使用的運算符它都可以用,但大多數運算都無意義的。
指針+n <=> 寬度*n+指針 前面n個元素
指針-n <=> 指針-寬度*n 后退n個元素
指針-指針 <=> (指針-指針)/寬度 計算出兩個指針之間相隔多少個元素
const與指針:
const int* p; 指針所指向的內存不可修改。當我們為了提高傳參的效率而使用指針時,傳參的效率高了,但變量也有被修改的風險,這種寫法可以保護指針所指向的內存。
int const *p; 同上
int * const p; 指針變量不可被修改
const int* const p; 指針變量和指針所指向的內存都不可修改。
int const * const p; 同上
指針數組與數組指針:
指針數組:就是由指針組成的數組,它的成員是指針變量。類型* arr[長度];
數組指針:專門指針數組的指針。類型 (*arr)[長度];
指針與數組名:
數組名是一種特殊的指針,它是常量,不能修改它的值,它與數組的內存是映射關系。數組名 == &數組名指針變量有自己的存儲空間,如果它存儲是數組的首地址,指針可以當數組使用,數組名也可以當指針使用。數組名[i] == *(數組名+1)數組作為函數的參數時入脫變成了指針,所以長度丟失。
二級指針:
二級指針就是指向指針的指針,里面存儲的是指針變量的地址。
定義:類型** 變量名_pp;
賦值:變量名 = &指針;
解引用:*變量名 <=> 指針**變量名 <=> *指針
函數指針:
函數名就個地址(整數),它代表函數在代碼段中所處的位置。函數指針就是指向函數的指針,它里面存儲是函數在代碼段中所處位置(函數名);typedef 返回值 (*函數指針)(類型1 參數名1,類型2 參數名2...);
函數指針 fp;使用了回調模式的庫函數:
// 快速排序
void qsort(void *base, size_t nmemb, size_t size,int(*compar)(const void *, const void *));// 二分查找
void *bsearch(const void *key, const void *base,size_t nmemb, size_t size,int (*compar)(const void *, const void *));