首頁 >後端開發 >C#.Net教程 >C語言中typedef的用法有哪些?

C語言中typedef的用法有哪些?

青灯夜游
青灯夜游原創
2020-07-18 14:23:2934648瀏覽

typedef的用法有:1、為基本資料型別定義新的型別名稱;2、為自訂資料型別(結構體、共用體和枚舉型別)定義簡潔的型別名稱;3、為陣列定義簡潔的型別名稱;4、為指標定義簡潔的名稱。

C語言中typedef的用法有哪些?

C語言允許使用者使用typedef 關鍵字來定義自己習慣的資料型別名稱,來取代系統預設的基本型別名稱、陣列型別名稱、指標型名稱與使用者自訂的結構型名稱、共用型名稱、枚舉型名稱等。

一旦使用者在程式中定義了自己的資料型別名稱,就可以在程式中用自己的資料型別名稱來定義變數的型別、陣列的型別、指標變數的型別與函數的型別等。

例如,C 語言在C99 之前並未提供布林類型,但我們可以使用typedef 關鍵字來定義一個簡單的布林類型,如下面的程式碼所示:

typedef int BOOL;
#define TRUE 1
#define FALSE 0

定義好之後,就可以像使用基本型別資料一樣使用它了,如下面的程式碼所示:

BOOL bflag=TRUE;

#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;

在上面的程式碼中,實際上完成了兩個動作:

1)、定義了一個新的結構類型,程式碼如下所示:

struct tagPoint
{
    double x;
    double y;
    double z;
} ;

其中,struct 關鍵字和tagPoint 一起構成了這個結構類型,無論是否存在typedef 關鍵字,這個結構都存在。

2)、使用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];

小心使用 typedef 带来的陷阱

接下来看一个简单的 typedef 使用示例,如下面的代码所示:

typedef char* PCHAR;
int strcmp(const PCHAR,const PCHAR);

在上面的代码中,“const PCHAR” 是否相当于 “const char*” 呢?

答案是否定的,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“char*const(一个指向char的常量指针)”。即它实际上相当于“char*const”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:

typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);

其实,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。

还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:

typedef static int INT_STATIC;

不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”。

相关推荐:《c语言教程

以上是C語言中typedef的用法有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn