1. 程式人生 > 其它 >C語言中的typedef介紹,和C++11中using的用法補充

C語言中的typedef介紹,和C++11中using的用法補充

轉載自typedef介紹
本文介紹C語言中的關鍵字 typedef 的用法。 在C++11中用using替代typedef

1 概述

typedef 為C語言的關鍵字,作用是為一種資料型別定義一個新名字,這裡的資料型別包括內部資料型別(int,char等)和自定義的資料型別(struct等)。

typedef 本身是一種儲存類的關鍵字,與 auto、extern、static、register 等關鍵字不能出現在同一個表示式中。

2 作用及用法

2.1 typedef的用法

使用 typedef 定義新型別的方法(步驟):在傳統的變數宣告表示式裡,用(新的)型別名替換變數名,然後把關鍵字 typedef 加在該語句的開頭就可以了。

下面以兩個示例,描述 typedef 的用法步驟。

示例1:

【第一步】:int a; ———— 傳統變數宣告表示式
【第二步】:int myint_t; ———— 使用新的型別名myint_t替換變數名a
【第三步】:typedef int myint_t; ———— 在語句開頭加上typedef關鍵字,myint_t就是我們定義的新型別
C++11:using myint_t=int;

示例2:

【第一步】:void (pfunA)(int a); ———— 傳統變數(函式)宣告表示式
【第二步】:void (
PFUNA)(int a); ———— 使用新的型別名PFUNA替換變數名pfunA
【第三步】:typedef void (*PFUNA)(int a);

———— 在語句開頭加上typedef關鍵字,PFUNA就是我們定義的新型別
C++11:using PFUNA=void(*)(int a) 表示一個函式指標

特別強調:上述兩個示例,僅僅為了演示 typedef 的用法步驟,便於新手記憶 typedef 的用法。在實際編寫程式碼時,只有“第三步”對應的語句會寫入程式碼中!

2.2 typedef的作用

typedef 的作用有以下幾點:

1)typedef 的一個重要用途是定義機器無關的型別。例如,定義一個叫“REAL”的浮點型別,該浮點型別在目標機器上可以獲得最高的精度:

typedef long double REAL;

如果在不支援 long double 的機器上執行相關程式碼,只需要修改對應的 typedef 語句,例如:

typedef double REAL;

或者:

typedef float REAL;

2)使用 typedef 為現有型別建立別名,給變數定義一個易於記憶且意義明確的新名字。例如:

typedef unsigned int UINT

3)使用 typedef 簡化一些比較複雜的型別宣告,例如:

typedef void (*PFunCallBack)(char* pMsg, unsigned int nMsgLen);

上述宣告引入了 PFunCallBack 型別作為函式指標的同義字,PFunCallBack 型別定義的指標會指向一個函式,該函式包含兩個型別分別為 char* 和 unsigned int 的引數,以及一個型別為 void 的返回值。通常,當函式的引數是一個回撥函式時,就可能會使用 typedef 來簡化宣告。

例如,承接上面的示例的後續示例如下:

RedisSubCommand(const string& strKey, PFunCallBack pFunCallback, bool bOnlyOne);

*注意:*上述語句中型別名 PFunCallBack 與變數名 pFunCallback 的大小寫區別。

RedisSubCommand 函式的第二個引數是一個回撥函式,因此通過“PFunCallBack pFunCallback”(即,型別+變數)的形式,給出對應回撥函式(pFunCallback)的地址。

在這個示例中,如果不使用 typedef 簡化宣告,RedisSubCommand 的函式宣告內容如下:

RedisSubCommand(const string& strKey, void (*pFunCallback)(char* pMsg, unsigned int nMsgLen), bool bOnlyOne); 

從上面兩個函式宣告可以看出,在不使用 typedef 的情況下,RedisSubCommand 函式的宣告會複雜得多,不利於程式碼的維護,同時增加出錯風險。

所以,在某些複雜的型別宣告中,使用 typedef 進行宣告的簡化是很有必要的。

3 typedef與#define

兩者的區別如下:

  • #define 進行簡單的進行字串替換。 #define 巨集定義可以使用 #ifdef、#ifndef 等來進行邏輯判斷,還可以使用 #undef 來取消定義。
  • typedef 是為一個型別起新名字。typedef 符合(C語言)範圍規則,使用 typedef 定義的變數型別,其作用範圍限制在所定義的函式或者檔案內(取決於此變數定義的位置),而巨集定義則沒有這種特性。

通常,使用 typedef 要比使用 #define 要好,特別是在有指標的場合裡。

下面列舉幾個示例。

3.1 示例1

程式碼如下:

typedef char* pStr1;
#define pStr2 char* 
pStr1 s1, s2;
pStr2 s3, s4;

在上述的變數定義中,s1、s2、s3都被定義為 char* 型別;但是s4則定義成了 char 型別,而不是我們所預期的指標變數 char*,這是因為 #define 只做簡單的字串替換,替換後的相關程式碼等同於為:

char* s3, s4;

而使用 typedef 為 char* 定義了新型別 pStr1 後,相關程式碼等同於為:

char *s3, *s4;

3.1 示例2

程式碼如下:

typedef char *pStr;
char string[5]="test";
const char *p1=string;
const pStr p2=string;
p1++;
p2++;

在編譯過程中,報錯如下:

根據上述錯誤資訊能夠看出,p2 為只讀常量,所以 p2++ 出錯了。這個問題再一次提醒我們:typedef 和 #define 不同,typedef 不是簡單的文字替換,上述程式碼中 const pStr p2 並不等於 const char * p2,pStr 是作為一個型別存在的,所以 const pStr p2 實際上是限制了 pStr 型別的 p2 變數,對 p2 常量進行了只讀限制。也就是說,const pStr p2 和 pStr const p2 本質上沒有區別(可類比 const int p2 和 int const p2),都是對變數 p2 進行只讀限制,只不過此處變數 p2 的資料型別是我們自己定義的 pStr,而不是系統固有型別(如 int)而已。

所以,const pStr p2 的含義是:限定資料型別為 char * 的變數 p2 為只讀,因此 p2++ 錯誤。

*注意:*在本示例中,typedef 定義的新型別與編譯系統固有的型別沒有差別。