至今已遇到兩個typedef詭異的定義,因此決定下筆記之,以備後用。
【typedef之const指針】
【案例】
typedef string * pstr;
const pstr cpstr;
問上述代碼中cpstr是一個怎樣的指針?
【分析】
很多朋友,包括我自己在剛接觸到時,第一反應是:cpstr被定義為一個指向const string對象的普通指針,原因很簡單,置換一下string*與pstr的位置就得到
//這顯然就是一個指向const string對象的普通指針
const string * cpstr;
然而,事不如人願,cpstr的確切定義為:一個指向string類型的const指針。
看到這個答案,相比不少朋友稍顯驚訝,我也如此,其中內因,且聽我慢慢道來。
之所以出錯,在於我們“置換一下就好了”,“置換”這個詞不應該用在typedef,而該用在#define宏身上,typedef是定義了一個類型別名,定義的結果遵循任何正常定義的標准。那麼這個typedef到底是怎麼定義了一個const指針呢?
首先分析
const pstr cpstr;
這段代碼定義了一個pstr類型的const cpstr,實際上就是
pstr const cpstr;
為了便於理解,就拿int定義來說
//二者等價,前者是習慣用法,後者是標准規定
const int ival = 0;
int const ival = 0;
既然理解了cpstr是一個const的pstr類型的對象,pstr是什麼呢?pstr是string*,因此這樣一來,就成了cpstr是一個const的string*類型的對象,也即cpstr是一個指向普通string的const指針。
【總結】
本次誤解主要源於大家認為typedef等同於#define宏定義,以為簡單替換字符就可以了。實則不然。以後見到這樣的定義,最簡單的辦法就是從定義該變量的地方入手
typedef string * pstr;
const pstr cpstr;
按步驟(熟練了就很快了)思考:
①cpstr是一個類型為 pstr 的常量
②pstr 是什麼?
③pstr 是 string*
④所以,cpstr是一個類型為 string* 的常量,也即 string *const cpstr
【typedef之函數類型】
【案例】
typedef int FUNC (int);
請問typedef定義了一個什麼類型?
【分析】
不要驚訝,就是這樣,它不是一個函數指針,也不是被我寫錯了。
它定義了一個函數類型FUNC,這個函數類型要求一個int形參,返回一個int結果。
【總結】
FUNC TestFunc(FUNC F);
FUNC的用法是有限制的,上述語句會導致編譯時錯誤。
上述代碼使用了兩次FUNC,出錯的是第一個,也就是FUNC類型的函數返回類型是有錯的。
FUNC是函數類型,在另一個函數中,函數類型變量只能夠用作另一個函數的形參,而不能是返回類型。
FUNC用作形參時,編譯器會自動將其轉換為FUNC* /*函數指針*/,而編譯器不會將作為函數返回類型的FUNC進行轉換,因此會出現編譯時錯誤,可修正如下
FUNC* TestFunc(FUNC F);
聲明了一個函數TestFunc,該函數要求一個函數類型為FUNC的函數F作為形參,並返回一個FUNC類型的函數指針FUNC*
【typedef與#define】
【案例】
typedef int* Tpi;
#define int* Dpi;
Tpi p1,p2;
Dpi p3,p4;
問上述代碼中定義的四個變量分別為什麼類型?
【分析】
區分p1,p2,p3,p4四個變量的類型,首先要理解typedef和#define宏的區別,typedef是給已有的類型取別名,而#define只是簡單的字符替換。於是上述代碼等同於
int *p1,*p2;//typedef的作用
int *p3,p4;//#define的作用
也就是說p3被定義為了一個整型指針,而p4則只是整型。
【總結】
需要掌握typedef與#define的區別,以防這些細微的陷阱,為高質量代碼做好保障。