相信每一個C++學習者都被C++的typedef const 數組 函數 指針之間的花式組合抓狂過,這都是啥?於是開個坑記錄下C++指針識別的一些技巧和坑點。
還在不斷更新中......
const和指針識別
const和指針的組合識別可以這樣:看const的右邊是誰,右邊是誰const就是修飾誰,
const int *p=&a; //這里const右邊是int,代表修飾的是常量,p是指向一個常量的指針,p指針本身能修改但其指向一個常量不能修改
int * const p=&a; //這里const右邊是p,代表修飾的是指針p,那么p是一個常指針,即p本身不能改變了,但是可以通過p改變其指向的值
值得注意的是上訴的第一種還可以寫成:int const* p=&a;這種寫法看起來是一個不能改變的常指針,但是其實它應該是和第一種寫法相同含義的,這種寫法容易混淆,我們更推薦使用上面第一種寫法。
關於const和指針的識別還有一種辦法:看const和*號的位置,const在左邊是指向常量的指針,const在右邊是常指針。
坑點:typedef char* ptr; const ptr cstr; (ptr const cstr;)
解答:看起來應該是 const char* cstr; 指向常量的指針。其實不是,此時const修飾的是ptr,ptr是一個指針,所以實際上cstr是一個指向char的常指針。即等於char * const cstr;
那么const ptr *cstr;這又是什么呢? 首先cstr是一個指針,它指向另一個指針,指向的指針是一個指向char的常指針。
數組指針與指針數組
這分辨這兩個區別值錢,必須先清楚,數組名本身就是一個指針,指向數組首元素地址。
數組指針①:int (*p)[n]; 首先觀察這個括號,括號優先級高代表p首先是一個指針,然后p指向一個長度為n的整型一維數組。
指針數組②:int *p[n]; 這里沒有小括號了,那么[]優先級高,即p首先是一個長度為n的數組,然后有*,那么p數組是一個指針數組,即其每一個元素都是一個 整型指針。
① int a[3][4]; int (*p)[4]; p=a; p++;
注意觀察,首先a是二維數組每一行長度為4,然后p是一個數組指針它指向長度為4的一維數組,那么p=a時候(相當於p=a[0] / p=&a[0][0]),p++過后p就跨過一行(a[0]這一行)指向了a[1]。
可以理解為這里的p是只有一個指針,孤軍奮戰內存中只有一個位置。
② int a[3][4]; int *p[3]; for (int i=0;i<3;i++) p[i]=a[i];
首先a還是一個3行4列的數組,p是一個指針數組,其每一個元素都是一個指針,所以經過for循環之后,p[0]指向了a數組第0行首地址,p[1]指向a數組第1行首地址......
可以理解為此時p是一個數組,他在內存中有4個位置,每一個都是指針類型。
函數指針
函數指針有什么用?函數指針指向函數地址,可以通過函數指針調用函數。簡單用法示例:
int add(int a,int b); //首先我們有一個函數
int (*pf) (int,int); //其次我們有一個指針pf,pf是一個函數指針它可以指向一個函數,指針未初始化。注意觀察:pf右邊是參數列表(int,int),pf左邊是函數返回值int。亦即pf可以指向一個參數列表為(int,int)返回值為int的函數。add是滿足條件的函數。
pf=add; //上面分析過了,pf是可以指向add函數的。
pf(a,b) //此時pf和add無差別了,都是調用這個函數。
注意pf兩邊的括號不能省略,否則變成返回值為int *類型的函數,函數名為pf。
typedef int (*PF) (int,int) ; PF pf;
上面這個用法即先typedef PF為一個函數指針類型,之后可以用PF去定義別人。
函數指針不僅僅是像上面那樣起到起別名的作用,還可以把函數指針當作函數參數傳給函數:
比如有幾個函數參數列表如下: void func(int a,int (*pf) (int,int) ); void func(int a,PF);
如果此時pf=add; 那么就可以之間把pf傳過去:func(a,pf); 這相當於func(a,add);
decltype關鍵字:
參考資料:
《C++Primer第五版》