官术网_书友最值得收藏!

建議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];

主站蜘蛛池模板: 沐川县| 任丘市| 峨山| 弥勒县| 突泉县| 三门县| 汝城县| 周宁县| 蓬莱市| 原阳县| 雅江县| 平远县| 朝阳市| 依安县| 黔南| 资兴市| 凤台县| 大同县| 靖西县| 锡林浩特市| 图们市| 赤峰市| 霍城县| 兰考县| 尼勒克县| 湟源县| 镇江市| 崇明县| 嘉祥县| 文安县| 团风县| 陆河县| 彭山县| 集安市| 枣阳市| 巴青县| 邢台县| 滕州市| 广水市| 邵阳市| 冷水江市|