C语言再学习 -- 关键字typedef
參看:C語言再學(xué)習(xí) -- 結(jié)構(gòu)和其他數(shù)據(jù)形式
參看:C語言再學(xué)習(xí) -- 關(guān)鍵字struct(轉(zhuǎn))
參看:常見typedef 用法
參看:關(guān)于typedef的用法總結(jié)
一、typedef 介紹
typedef為C語言的關(guān)鍵字,作用是為一種數(shù)據(jù)類型定義一個(gè)新名字。比如人們常常使用 typedef 來編寫更美觀和可讀的代碼。所謂美觀,意指 tepedef 能隱藏笨拙的語法構(gòu)造以及平臺(tái)相關(guān)的數(shù)據(jù)類型,從而增強(qiáng)可移植性以及未來的可維護(hù)性。
這里的數(shù)據(jù)類型包括內(nèi)部數(shù)據(jù)類型(int,char等)和自定義的數(shù)據(jù)類型(struct等)。 在編程中使用typedef目的一般有兩個(gè),一個(gè)是給變量一個(gè)易記且意義明確的新名字,另一個(gè)是簡(jiǎn)化一些比較復(fù)雜的類型聲明。
typedef 使用方法如下:
typedef existing_type new_type_name; 注意:typedef 并不創(chuàng)建新的類型。它僅僅為現(xiàn)有類型添加一個(gè)同義字。
typedef的簡(jiǎn)單應(yīng)用:
typedef unsigned char BYTE; BYTE b1, b2;
在這個(gè)類型定義之后,標(biāo)識(shí)符 BYTE 可作為類型 unsigned char 的縮寫。該定義的作用域取決于 typedef 語句所在的位置。如果定義是在一個(gè)函數(shù)內(nèi)部,它的作用域是局部的,限定在那個(gè)函數(shù)里。如果定義是在函數(shù)外部,它將具有全局作用域。
通常,這些定義使用大寫字母,以提醒用戶這個(gè)類型名稱實(shí)際上是一個(gè)符號(hào)縮寫。不過,您也可以使用小寫字母。
二、typedef 用法總結(jié)
1、typedef 與 define 區(qū)別
首先你要了解 typedef 和 define 的區(qū)別,宏定義只是簡(jiǎn)單的字符串代換,是在預(yù)處理完成的,而typedef是在編譯時(shí)處理的,它不是作簡(jiǎn)單的代換,而是對(duì)類型說明符重新命名。被命名的標(biāo)識(shí)符具有類型定義說明的功能。
請(qǐng)看下面的例子:
#define P1 int *
typedef (int *) P2
從形式上看這兩者相似,但在實(shí)際使用中卻不相同。
下面用P1、P2說明變量時(shí)就可以看出它們的區(qū)別:
P1 a, b; ?在宏代換后變成: int *a, b; ?表示 a 是指向整型的指針變量,而 b 是整型變量。
P2 a, b; ?表示a,b都是指向整型的指針變量。因?yàn)镻IN2是一個(gè)類型說明符。
由這個(gè)例子可見,宏定義雖然也可表示數(shù)據(jù)類型, 但畢竟是作字符代換。在使用時(shí)要分外小心,以避出錯(cuò)。
總結(jié),typedef和#define的不同之處:
1、與#define不同,typedef 給出的符號(hào)名稱僅限于對(duì)類型,而不是對(duì)值。
2、typedef 的解釋由編譯器,而不是是處理器執(zhí)行。
3、雖然它的范圍有限,但在其受限范圍內(nèi),typedef 比 #define 更靈活。
2、常規(guī)變量類型定義
typedef 聲明可用來表示一個(gè)變量的含義。
例如:typedef unsigned char uchar
描述:uchar等價(jià)于unsigned char類型定義
? ? ? ? ? ?uchar c聲明等于unsigned char c聲明
3、數(shù)組類型定義
例如: typedef int array[2];
描述: array等價(jià)于 int [2]定義;
? ? ? ? ? ? array a聲明等價(jià)于int a[2]聲明
擴(kuò)展: typedef int array[M][N];
描述: array等價(jià)于 int [M][N]定義;
? ? ? ? ? ? array a聲明等價(jià)于int a[M][N]聲明
4、指針類型定義
例如: typedef int *pointer;
描述: pointer等價(jià)于 int *定義;
? ? ? ? ? ? pointer p聲明等價(jià)于int *p聲明
例如: typedef int *pointer[M];
描述: pointer等價(jià)于 int *[M]定義;
? ? ? ? ? ? pointer p聲明等價(jià)于int *p[M]聲明
5、函數(shù)地址說明
描述: C把函數(shù)名字當(dāng)做函數(shù)的首地址來對(duì)待,我們可以使用最簡(jiǎn)單的方法得到函數(shù)地址
例如: 函數(shù):int func(void);
? ? ? ? ? ? unsigned long funcAddr=(unsigned long)func;
? ? ? ? ? ? funcAddr的值是func函數(shù)的首地址
6、函數(shù)聲明
例如: typedef int func(void); ?
? ? ? ? ? ? func等價(jià)于 int (void)類型函數(shù)
描述1: func f聲明等價(jià)于 int f(void)聲明,用于文件的函數(shù)聲明
描述2: func *pf聲明等價(jià)于 int (*pf)(void)聲明,用于函數(shù)指針的聲明,見下一條
7、函數(shù)指針
例如: typedef int (*func)(void)
描述: func等價(jià)于int (*)(void)類型
? ? ? ? ? ? func pf等價(jià)于int (*pf)(void)聲明,pf是一個(gè)函數(shù)指針變量
8、識(shí)別typedef的方法:
a).第一步。使用已知的類型定義替代 typdef 后面的名稱,直到只剩下一個(gè)名字不識(shí)別為正確
? ? 如typedef u32 ? (*func)(u8);
? ? 從上面的定義中找到 typedef __u32 ?u32; typedef __u8 u8
? ? 繼續(xù)找到 typedef unsigned int __u32; typedef unsigned char __u8;
? ? 替代位置名稱 typedef unsigned int ?(*func)(void);
? ? 現(xiàn)在只有func屬于未知
b).第二步.未知名字為定義類型,類型為取出名稱和 typedef 的所有部分,如上為
? ? func等價(jià)于unsigned unsigned ?int ?(*)(unsigned ?char);
c).第三部.定義一個(gè)變量時(shí),變量類型等價(jià)于把變量替代未知名字的位置所得到的類型
? ? func f等價(jià)于unsigned unsigned int ?(*f)(unsigned char)
9、結(jié)構(gòu)體定義
結(jié)構(gòu)體的一般定義形式為:
標(biāo)簽(tag)字段允許為成員列表提供一個(gè)名字,這樣它就可以在后續(xù)的聲明中使用。標(biāo)簽允許多個(gè)聲明使用同一個(gè)成員列表,并且創(chuàng)建同一種類型的結(jié)構(gòu)。
[cpp]?view plaincopy10、結(jié)構(gòu)體指針
struct Node {int data;struct Node *nextptr; };
使用 typede 上面的代碼可以改寫為如下:
typedef struct Node pNode; struct Node {int data;pNode *nextptr; };
或者
typedef struct Node{int data;struct Node *nextptr; }pNode;
三、typedef 用途
用途一:與#define的區(qū)別
typedef 行為有點(diǎn)像 #define 宏,用其實(shí)際類型替代同義字。不同點(diǎn)是 typedef 在編譯時(shí)被解釋,
因此讓編譯器來應(yīng)付超越預(yù)處理器能力的文本替換。
?用途二:減少錯(cuò)誤
定義一種類型的別名,而不只是簡(jiǎn)單的宏替換。可以用作同時(shí)聲明指針型的多個(gè)對(duì)象。比如:
[cpp]?view plaincopy print?
以下則可行:
[cpp]?view plaincopy print?
這種用法很有用,特別是char* pa, pb的定義,初學(xué)者往往認(rèn)為是定義了兩個(gè)字符型指針,其實(shí)不是,而用typedef char* PCHAR就不會(huì)出現(xiàn)這樣的問題,減少了錯(cuò)誤的發(fā)生。
用途三: ? ?直觀簡(jiǎn)潔
用在舊的C代碼中,幫助struct。以前的代碼中,聲明struct新對(duì)象時(shí),必須要帶上struct,即形式為: struct 結(jié)構(gòu)名對(duì)象名,如:
[cpp]?view plaincopy print?
而在C++中,則可以直接寫:結(jié)構(gòu)名對(duì)象名,即:tagPOINT1 p1;
[cpp]?view plaincopy print?
POINT p1; // 這樣就比原來的方式少寫了一個(gè)struct,比較省事,尤其在大量使用的時(shí)候,或許,在C++中,typedef的這種用途二不是很大,但是理解了它,對(duì)掌握以前的舊代碼還是有幫助的,畢竟我們?cè)陧?xiàng)目中有可能會(huì)遇到較早些年代遺留下來的代碼。
用途四:平臺(tái)無關(guān)性
用typedef來定義與平臺(tái)無關(guān)的類型。
typedef 有另外一個(gè)重要的用途,那就是定義機(jī)器無關(guān)的類型,例如,你可以定義一個(gè)叫 REAL 的浮點(diǎn)類型,在目標(biāo)機(jī)器上它可以獲得最高的精度:? [cpp]?view plaincopy print?
也就是說,當(dāng)跨平臺(tái)時(shí),只要改下 typedef 本身就行,不用對(duì)其他源碼做任何修改。
標(biāo)準(zhǔn)庫就廣泛使用了這個(gè)技巧,比如size_t。另外,因?yàn)閠ypedef是定義了一種類型的新別名,不是簡(jiǎn)單的字符串替換,所以它比宏來得穩(wěn)健。
用途五:掩飾復(fù)合類型
typedef 還可以掩飾復(fù)合類型,如指針和數(shù)組。?
例如,你不用像下面這樣重復(fù)定義有 81 個(gè)字符元素的數(shù)組:? [cpp]?view plaincopy print?
用途六:代碼簡(jiǎn)化
代碼簡(jiǎn)化。為復(fù)雜的聲明定義一個(gè)新的簡(jiǎn)單的別名。方法是:在原來的聲明里逐步用別名替換一部分復(fù)雜聲明,如此循環(huán),把帶變量名的部分留到最后替換,得到的就是原聲明的最簡(jiǎn)化版。舉例:?
?原聲明:
[cpp]?view plaincopy print?
變量名為b,先替換右邊部分括號(hào)里的,pFunParam為別名
[cpp]?view plaincopy print?
再替換左邊的變量b,pFunx為別名二:
[cpp]?view plaincopy print?
原聲明的最簡(jiǎn)化版:
[cpp]?view plaincopy print?
原聲明:
[cpp]?view plaincopy print?
變量名為e,先替換左邊部分,pFuny為別名一:
[cpp]?view plaincopy print?
再替換右邊的變量e,pFunParamy為別名二
[cpp]?view plaincopy print?
原聲明的最簡(jiǎn)化版:
[cpp]?view plaincopy print?
理解復(fù)雜聲明可用的“右左法則”:從變量名看起,先往右,再往左,碰到一個(gè)圓括號(hào)就調(diào)轉(zhuǎn)閱讀的方向;括號(hào)內(nèi)分析完就跳出括號(hào),還是按先右后左的順序,如此循環(huán),直到整個(gè)聲明分析完。舉例:
[cpp]?view plaincopy print?
首先找到變量名func,外面有一對(duì)圓括號(hào),而且左邊是一個(gè)*號(hào),這說明func是一個(gè)指針;然后跳出這個(gè)圓括號(hào),先看右邊,又遇到圓括號(hào),這說明(*func)是一個(gè)函數(shù),所以func是一個(gè)指向這類函數(shù)的指針,即函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值類型是int。
[cpp]?view plaincopy print?
func右邊是一個(gè)[]運(yùn)算符,說明func是具有5個(gè)元素的數(shù)組;func的左邊有一個(gè)*,說明func的元素是指針(注意這里的*不是修飾func,而是修飾func[5]的,原因是[]運(yùn)算符優(yōu)先級(jí)比*高,func先跟[]結(jié)合)。跳出這個(gè)括號(hào),看右邊,又遇到圓括號(hào),說明func數(shù)組的元素是函數(shù)類型的指針,它指向的函數(shù)具有int*類型的形參,返回值類型為int。
用途七:typedef 和存儲(chǔ)類關(guān)鍵字(storage class specifier)?
這種說法是不是有點(diǎn)令人驚訝,typedef 就像 auto,extern,mutable,static,和 register 一樣,是一個(gè)存儲(chǔ)類關(guān)鍵字。這并不是說 typedef 會(huì)真正影響對(duì)象的存儲(chǔ)特性;它只是說在語句構(gòu)成上,typedef 聲明看起來象 static,extern 等類型的變量聲明。下面將帶到第二個(gè)陷阱:?
[cpp]?view plaincopy print?編譯通不過。問題出在你不能在聲明中有多個(gè)存儲(chǔ)類關(guān)鍵字。因?yàn)榉?hào) typedef 已經(jīng)占據(jù)了存儲(chǔ)類關(guān)鍵字的位置,在 typedef 聲明中不能用 register(或任何其它存儲(chǔ)類關(guān)鍵字)。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的C语言再学习 -- 关键字typedef的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言再学习 -- 关键字struct(
- 下一篇: 3、WordCount源码分析