程式扎記: [C++ 文章收集] 教學 : typedef 知多少?

標籤

2011年5月4日 星期三

[C++ 文章收集] 教學 : typedef 知多少?

轉載自 這理 
前言 : 
很多寫 C/C++ 的人都把 typedef 當成#define 來使用. 直覺像這樣的定義 : 

  1. typedef unsigned short WORD;  
就相當於 : 

  1. #define WORD unsigned short  
但就本義來說,#define 是字串的取代. 編譯器不會有任何的抗議就通過的,在程式任何使用到 WORD 的地方編譯器會忠實的用 unsigned short 取代 WORD. 由於取代的字串可不限於一行且可代入參數,所以#define 可用於 Macro 的定義如 : 

  1. #define max(a,b) (((a) > (b)) ? (a) : (b))  
回過頭來說typedef主題,從本義來說typedef是 C/C++ 型態的別名. 所以若你想 : 

  1. typedef Hello! WORD;  
那麼編譯器會給你一個難堪錯誤訊息!因為 Hello! 不是一個合法的型態,你不能為它取型態別名! typedef看來不怎麼有用是吧!?非也,由於所謂 C/C++ 的型態是很廣義的,使用typedef 可以使程式看起來簡潔易懂且不容易出錯. 下面是幾個typedef的應用例子. 

使用範例 : 
- 簡單型態的別名 
這三行沒什麼大不了,用#define也可以做 : 

  1. typedef unsigned char BYTE;//定義無號單字節的型態   
  2. typedef unsigned short WORD;//定義無號雙字節的型態   
  3. typedef unsigned long DWORD;//定義無號四字節的型態  
- 結構型態的別名 

  1. typedef struct StructTag{   
  2.     int mA;   
  3.     int mB;   
  4. }STRUCTTAG, *PSTRUCTTAG;  
當要建立這個結構的物件時,就可以用別名 STRUCTTAG 和 PSTRUCTTAG,例如 : 

  1. STRUCTTAG StructObj;   
  2. PSTRUCTTAG pStructObj;  
就相當於 

  1. struct StructTag StructObj;   
  2. struct StructTag *pStructObj;  
- 函式型態的別名 
如果你有一個 library 提供了字串轉整數的函式 : 

  1. int HexToInt(char *str);//十六進位字串轉整數   
  2. int DecToInt(char *str);//十進位字串轉整數  
當你的程式要使用這些函式時,就必需include這些函式的定義,但用typedef會更簡潔 : 

  1. typedef int ToInt(char *str);   
  2. //上面這行定義了一個需傳入字串(char *)且返回整數(int)的函式型態別名   
  3. //叫 ToInt   
  4. ToInt HexToInt,DecToInt;//宣告HexToInt,DecToInt這兩個函式  
現在你的程式可以呼叫HexToInt(...),DecToInt(...)了. 
在Windows,通常是應用程式呼叫API來工作的,但由於某種需求,Windows API 會反過來呼叫應用程式的函式,這種函式稱之為 callback function. callback function 對API來說只有該傳入那些參數和返回值型態,沒有函式名稱而用函式指標來呼叫(事實上Windows也不可能用程式的函式名稱來呼叫). 這時使用函式型態的別名來宣告函式指標就特別好用了. 舉個例子吧!建立一個新的行程(Thread)的函式 : 

HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,

__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);

其中 LPTHREAD_START_ROUTINE 就是一個函式型態的別名. 它的定義是 : 

  1. typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (  
  2.     [in] LPVOID lpThreadParameter  
  3. );  
用這個宣告,不論API或應用程式本身都很方便. 

補充說明 : 
* [C++ 文章收集] C++ 前置處理器 
* [ C Gossip ] 函式 : 進階議題 (函 式指標)

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!