C語言學習及應用筆記之五:C語言typedef關鍵字及其使用
在C語言中有一個typedef關鍵字,其用來定義用戶自定義類型。當然,並不是真的創造了一種數據類型,而是給已有的或者符合型的以及復雜的數據類型取一個我們自己更容易理解的別名。總之,可以使用typedef關鍵字定義一個我們自己的類型名稱。
那麽,究竟如何定義,又有哪些情況下可已使用呢?接下來我們就對它的幾種用法進行說明:
(1)基本數據類型定義
有些時候,我們會使用typedef關鍵字對一些基本數據類型進行重新定義。例如我們使用標準整數的數據類型uint8_t和uint16_t等時,其實他們的定義如下:
typedef unsigned char uint8_t; //無符號
typedef signed char int8_t; //有符號8位數
typedef unsigned int uint16_t; //無符號16位數
typedef signed int int16_t; //有符號16位數
typedef unsigned long uint32_t; //無符號32位數
typedef signed long int32_t; //有符號32位數
很顯然就是使用了typedef關鍵字給既有數據類型分配了一個別名。當我們使用uint8_t時,就和使用unsigned char
(2)指針數據類型定義
有些時候我們也會使用typedef關鍵字定義指針數據類型,用以簡化我們所使用的指針變量的聲明。
例如:typedef int *pointer;
這樣我們就定義了一個指針類型,當我們使用pointer p聲明一個指針變量,就和使用int *p的含義是一樣的。
上面是一個指針變量類型,可以演化出很多用法,如定義數組對象可以更明確。有時候,我們也定義指向二位數組行的指針,使用typedef關鍵字就可以使得操作更符合我們的常規認知。
例如: typedef int (*pointer
這裏pointer等價於 int (*)[N],當我們聲明pointer p就相當於聲明int (*a)[N]。同樣的,如果我們對二維數組采用類似的定義。
例如:typedef int array[M][N];
那它的含義與指針是類似的,如我們定義array a就是聲明了一個M行N列的數組,此時使用p=a是可以的。
我們考慮到數組很多時候可以使用指針表示,所以將其放在一起討論,而其它一些對象指針我們單獨討論。其實,不光是上述數組和指針可以使用typedef關鍵字定義別名,其它如:一維和多位數組,指針數組等都可以這樣使用。
(3)用戶對象類型定義
首先說明,這裏說所的用戶對象是指結構體、聯合體以及枚舉等用戶定義的數據類型。我們可以使用typedef關鍵字給結構體等類型定義一個別名,這樣我們客氣在多個地方更方便的使用它。當然很多人對此有不同看法,這裏不討論,我們只是說有這種用法。
使用typedef關鍵字為結構體類型定義一個別名。
例如:typedef struct{
float setpoint; /*設定值*/
float kp; /*比例系數*/
float ki; /*積分系數*/
float kd; /*微分系數*/
float lasterror; /*前一拍偏差*/
float preerror; /*前兩拍偏差*/
float deadband; /*死區*/
float result; /*PID控制器計算結果*/
float output; /*輸出值0-100%*/
float maximum; /*輸出值上限*/
float minimum; /*輸出值下限*/
float errorabsmax; /*偏差絕對值最大值*/
float errorabsmin; /*偏差絕對值最小值*/
float alpha; /*不完全微分系數*/
float deltadiff; /*微分增量*/
float integralValue; /*積分累計量*/
float gama; /*微分先行濾波系數*/
float lastPv; /*上一拍的過程測量值*/
float lastDeltaPv; /*上一拍的過程測量值增量*/
}CLASSICPID;
這樣我們在需要使用結構體類型定義一個對象時,我們可以使用CLASSICPID vPID就可以了與使用原始定義是一樣的。
同樣我們也可以使用typedef關鍵字為枚舉類型定義一個別名。
例如:typedef enum {
FC_REG_Write=((uint8_t)0x80), /*寫寄存器的功能碼*/
FC_REG_Read=((uint8_t)0x81), /*讀寄存器的功能碼*/
FC_VAR_Write=((uint8_t)0x82), /*寫變量的功能碼*/
FC_VAR_Read=((uint8_t)0x83), /*讀變量的功能碼*/
FC_Curve_Write=((uint8_t)0x84) /*寫曲線緩沖區的功能碼*/
}DwinFunctionCode;
我們需要定義枚舉變量時,也是使用DwinFunctionCode fc就可以了。當然,我們也可已使用定義的類型聲明指針變量,或者直接使用typedef關鍵字定義指向對象的指針類型,如定義結構體指針類型。
(4)函數類型定義
typedef關鍵字也常用來定義函數類型,用以聲明同類型的函數或者函數指針變量。這一種類型定義在函數用作形參等一回調的方式使用時,非常有用,具體用法可參考回調函數的使用。
使用typedef關鍵字定義函數類型與前面的各種定義方式類式。
例如: typedef int fType(void);
在這裏fType等價於 int (void)類型函數。如果我們使用fType function聲明函數function時,與使用int function (void)來聲明是一樣的。
同樣我們也可以使用fType來定義函數指針。如果我們使用fType *fPointer聲明函數指針fPointer時,和使用int (*fPointer) (void)來聲明是一樣的。
當然,我們也可以使用typedef關鍵字直接定義函數指針類型。
例如: typedef int (*fPointer)(void);
這樣我們就可以使用fPointer來定義一個函數指針。如我們使用fPointer fp聲明函數指針就如同使用int (*fp)(void)來聲明。
(5)typedef關鍵字與宏定義
我們已經說明了typedef關鍵字的基本用法。但我們發現它的功能視乎宏定義也能實現,所以我們接下來說明一下typedef關鍵字和#define定義的宏之間究竟有何不同。
從功能範圍上講是有區別的,typedef主要是為已存在的關鍵字或類型及其組合取一個我們容易識別的別名。在這一點上#define也可實現,但初次之外#define還有很多其它用處,如果願意你可以使用它定義任何代碼,這時typedef所不具備的。
執行時間也是有區別的,對於#define定義的宏,其在預處理階段就會被替換。而typedef定義的類型會在編譯時處理。
從作用於上來講也是有區別的,一般來說#define定義的宏沒有作用於的限制,只要在使用前有定義就可以了。而typedef定義的別名是有作用於的。
從實現效果來講也是有區別的,我們使用typedef定義一個指針類型,然後使用該類型可以同時聲明對各變量,而#define卻不是這樣的。如typedef (int*) pType;可以使用pType a,b;這裏a和b都是指向整數的指針變量。但我們同樣定義#define pType int*,若使用pType a,b;定義a和b,則a是指向整數的指針變量,而b不是。
歡迎關註:
C語言學習及應用筆記之五:C語言typedef關鍵字及其使用