- 編寫高質量代碼:改善C程序代碼的125個建議
- 馬偉 著
- 1496字
- 2019-01-01 01:33:13
建議6-1:掌握typedef的4種應用形式
在實際使用中,typedef的應用主要有如下4種形式。
1.為基本數據類型定義新的類型名
也就是說,系統默認的所有基本類型都可以利用typedef關鍵字來重新定義類型名,示例代碼如下所示:
typedef unsigned int COUNT;
而且,我們還可以使用這種方法來定義與平臺無關的類型。比如,要定義一個叫REAL的浮點類型,在目標平臺一上,讓它表示最高精度的類型,即:
typedef long double REAL;
在不支持long double的平臺二上,改為:
typedef double REAL;
甚至還可以在連double都不支持的平臺三上,改為:
typedef float REAL;
這樣,當跨平臺移植程序時,我們只需要修改一下typedef的定義即可,而不用對其他源代碼做任何修改。其實,標準庫中廣泛地使用了這個技巧,比如size_t在VC++2010的crtdefs.h文件中的定義如下所示:
#ifndef _SIZE_T_DEFINED #ifdef _WIN64 typedef unsigned __int64 size_t; #else typedef _W64 unsigned int size_t; #endif #define _SIZE_T_DEFINED #endif
2.為自定義數據類型(結構體、共用體和枚舉類型)定義簡潔的類型名稱
以結構體為例,下面我們定義一個名為Point的結構體:
struct Point { double x; double y; double z; };
在調用這個結構體時,我們必須像下面的代碼這樣來調用這個結構體:
struct Point oPoint1={100,100,0}; struct Point oPoint2;
在這里,結構體struct Point為新的數據類型,在定義變量的時候均要向上面的調用方法一樣有保留字struct,而不能像int和double那樣直接使用Point來定義變量。現在,我們利用typedef定義這個結構體,如下面的代碼所示:
typedef struct tagPoint { double x; double y; double z; } Point;
在上面的代碼中,實際上完成了兩個操作:
□ 定義了一個新的結構類型,代碼如下所示:
struct tagPoint { double x; double y; double z; } ;
其中,struct關鍵字和tagPoint一起構成了這個結構類型,無論是否存在typedef關鍵字,這個結構都存在。
□ 使用typedef為這個新的結構起了一個別名,叫Point,即:
typedef struct tagPoint Point
因此,現在你就可以像int和double那樣直接使用Point定義變量,如下面的代碼所示:
Point oPoint1={100,100,0}; Point oPoint2;
為了加深對typedef的理解,我們再來看一個結構體例子,如下面的代碼所示:
typedef struct tagNode { char *pItem; pNode pNext; } *pNode;
從表面上看,上面的示例代碼與前面的定義方法相同,所以應該沒有什么問題。但是編譯器卻報了一個錯誤,為什么呢?莫非C語言不允許在結構中包含指向它自己的指針?
其實問題并非在于struct定義的本身,大家應該都知道,C語言是允許在結構中包含指向它自己的指針的,我們可以在建立鏈表等數據結構的實現上看到很多這類例子。那問題在哪里呢?其實,根本問題還是在于typedef的應用。
在上面的代碼中,新結構建立的過程中遇到了pNext聲明,其類型是pNode。這里要特別注意的是,pNode表示的是該結構體的新別名。于是問題出現了,在結構體類型本身還沒有建立完成的時候,編譯器根本就不認識pNode,因為這個結構體類型的新別名還不存在,所以自然就會報錯。因此,我們要做一些適當的調整,比如將結構體中的pNext聲明修改成如下方式:
typedef struct tagNode { char *pItem; struct tagNode *pNext; } *pNode;
或者將struct與typedef分開定義,如下面的代碼所示:
typedef struct tagNode *pNode; struct tagNode { char *pItem; pNode pNext; };
在上面的代碼中,我們同樣使用typedef給一個還未完全聲明的類型tagNode起了一個新別名。不過,雖然C語言編譯器完全支持這種做法,但不推薦這樣做。建議還是使用如下規范定義方法:
struct tagNode { char *pItem; struct tagNode *pNext; }; typedef struct tagNode *pNode;
3.為數組定義簡潔的類型名稱
它的定義方法很簡單,與為基本數據類型定義新的別名方法一樣,示例代碼如下所示:
typedef int INT_ARRAY_100[100]; INT_ARRAY_100 arr;
4.為指針定義簡潔的名稱
對于指針,我們同樣可以使用下面的方式來定義一個新的別名:
typedef char* PCHAR; PCHAR pa;
對于上面這種簡單的變量聲明,使用typedef來定義一個新的別名或許會感覺意義不大,但在比較復雜的變量聲明中,typedef的優勢馬上就體現出來了,如下面的示例代碼所示:
int *(*a[5])(int, char*);
對于上面變量的聲明,如果我們使用typdef來給它定義一個別名,這會非常有意義,如下面的代碼所示:
// PFun是我們創建的一個類型別名 typedef int *(*PFun)(int, char*); // 使用定義的新類型來聲明對象,等價于int* (*a[5])(int, char*); PFun a[5];
- LaTeX Cookbook
- C#完全自學教程
- Windows系統管理與服務配置
- Python王者歸來
- Java EE 7 Development with NetBeans 8
- 用Flutter極速構建原生應用
- 你不知道的JavaScript(中卷)
- INSTANT Adobe Edge Inspect Starter
- INSTANT Silverlight 5 Animation
- Learning Material Design
- Arduino Wearable Projects
- Android應用開發實戰(第2版)
- Cinder:Begin Creative Coding
- Expert Cube Development with SSAS Multidimensional Models
- R語言編程基礎