typedef struct 用法詳解和用法小結(jié)_第1頁
typedef struct 用法詳解和用法小結(jié)_第2頁
typedef struct 用法詳解和用法小結(jié)_第3頁
typedef struct 用法詳解和用法小結(jié)_第4頁
typedef struct 用法詳解和用法小結(jié)_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、1. 基本解釋typedef為C語言的關(guān)鍵字,作用是為一種數(shù)據(jù)類型定義一個新名字。這里的數(shù)據(jù)類型包括內(nèi)部數(shù)據(jù)類型(int,char等)和自定義的數(shù)據(jù)類型(struct等)。在編程中使用typedef目的一般有兩個,一個是給變量一個易記且意義明確的新名字,另一個是簡化一些比較復(fù)雜的類型聲明。至于typedef有什么微妙之處,請你接著看下面對幾個問題的具體闡述。2. typedef & 結(jié)構(gòu)的問題當用下面的代碼定義一個結(jié)構(gòu)時,編譯器報了一個錯誤,為什么呢?莫非C語言不允許在結(jié)構(gòu)中包含指向它自己的指針嗎?請你先猜想一下,然后看下文說明:typedef struct tagNodechar *

2、pItem;pNode pNext; *pNode; 答案與分析:1、typedef的最簡單使用typedef long byte_4; 給已知數(shù)據(jù)類型long起個新名字,叫byte_4。2、 typedef與結(jié)構(gòu)結(jié)合使用typedef struct tagMyStruct int iNum;long lLength; MyStruct; 這語句實際上完成兩個操作:1) 定義一個新的結(jié)構(gòu)類型struct tagMyStruct int iNum; long lLength; ; 分析:tagMyStruct稱為“tag”,即“標簽”,實際上是一個臨時名字,struct 關(guān)鍵字和tagMyStr

3、uct一起,構(gòu)成了這個結(jié)構(gòu)類型,不論是否有typedef,這個結(jié)構(gòu)都存在。我們可以用struct tagMyStruct varName來定義變量,但要注意,使用tagMyStruct varName來定義變量是不對的,因為struct 和tagMyStruct合在一起才能表示一個結(jié)構(gòu)類型。2) typedef為這個新的結(jié)構(gòu)起了一個名字,叫MyStruct。typedef struct tagMyStruct MyStruct; 因此,MyStruct實際上相當于struct tagMyStruct,我們可以使用MyStruct varName來定義變量。答案與分析C語言當然允許在結(jié)構(gòu)中包含指

4、向它自己的指針,我們可以在建立鏈表等數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)上看到無數(shù)這樣的例子,上述代碼的根本問題在于typedef的應(yīng)用。根據(jù)我們上面的闡述可以知道:新結(jié)構(gòu)建立的過程中遇到了pNext域的聲明,類型是pNode,要知道pNode表示的是類型的新名字,那么在類型本身還沒有建立完成的時候,這個類型的新名字也還不存在,也就是說這個時候編譯器根本不認識pNode。解決這個問題的方法有多種:1)、typedef struct tagNode char *pItem;struct tagNode *pNext; *pNode; 2)、typedef struct tagNode *pNode;struct ta

5、gNode char *pItem;pNode pNext; 注意:在這個例子中,你用typedef給一個還未完全聲明的類型起新名字。C語言編譯器支持這種做法。3)、規(guī)范做法:typedef uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 );這個以前沒有看到過,個人認為是宇定義一個uint32的指針函數(shù),uint16*, uint32 為函數(shù)里的兩個參數(shù); 應(yīng)該相當于#define uint32 (* ADM_READDATA_PFUNC)( uint16*, uint32 ); struct在代碼中常見兩種形式: struct A /. ; s

6、truct /. A; 這其實是兩個完全不同的用法: 前者叫做“結(jié)構(gòu)體類型定義”,意思是:定義中的結(jié)構(gòu)為一個名稱是“A”的結(jié)構(gòu)體。 這種用法在typedef中一般是: typedef struct tagA /故意給一個不同的名字,作為結(jié)構(gòu)體的實名 /. A; /結(jié)構(gòu)體的別名。 后者是結(jié)構(gòu)體變量定義,意思是:以中的結(jié)構(gòu),定義一個名稱為"A"的變量。這里的結(jié)構(gòu)體稱為匿名結(jié)構(gòu)體,是無法被直接引用的。 也可以通過typedef為匿名結(jié)構(gòu)體創(chuàng)建一個別名,從而使得它可以被引用: typedef struct /. A; /定義匿名結(jié)構(gòu)體的別名為A 第二篇:在C和C+中struct和t

7、ypedef struct的區(qū)別 在C和C+有三種定義結(jié)構(gòu)的方法。 typedef struct int data; int text; S1; /這種方法可以在c或者c+中定義一個S1結(jié)構(gòu)struct S2 int data; int text; ; / 這種定義方式只能在C+中使用,而如果用在C中,那么編譯器會報錯 struct int data; int text; S3; 這種方法并沒有定義一個結(jié)構(gòu),而是定義了一個s3的結(jié)構(gòu)變量,編譯器會為s3內(nèi)存。 void main() S1 mine1;/ OK ,S1 是一個類型 S2 mine2;/ OK,S2 是一個類型 S3 mine3;

8、/ OK,S3 不是一個類型 S1.data = 5;/ ERRORS1 是一個類型 S2.data = 5;/ ERRORS2 是一個類型 S3.data = 5;/ OKS3是一個變量 另外,對與在結(jié)構(gòu)中定義結(jié)構(gòu)本身的變量也有幾種寫法 struct S6 S6* ptr; ; / 這種寫法只能在C+中使用 typedef struct S7* ptr; S7; / 這是一種在C和C+中都是錯誤的定義 如果在C中,我們可以使用這樣一個“曲線救國的方法“ typedef struct tagS8 tagS8 * ptr; S8;第三篇:struct和typedef struct 分三塊來講述:

9、1 首先: 在C中定義一個結(jié)構(gòu)體類型要用typedef:typedef struct Studentint a;Stu;于是在聲明變量的時候就可:Stu stu1;如果沒有typedef就必須用struct Student stu1;來聲明這里的Stu實際上就是struct Student的別名。另外這里也可以不寫Student(于是也不能struct Student stu1;了)typedef structint a;Stu;但在c+里很簡單,直接struct Studentint a;于是就定義了結(jié)構(gòu)體類型Student,聲明變量時直接Student stu2;=2其次: 在c+中如果用

10、typedef的話,又會造成區(qū)別:struct Student int a; stu1;/stu1是一個變量 typedef struct Student2 int a; stu2;/stu2是一個結(jié)構(gòu)體類型 使用時可以直接訪問stu1.a但是stu2則必須先 stu2 s2;然后 s2.a=10;=3 掌握上面兩條就可以了,不過最后我們探討個沒多大關(guān)系的問題如果在c程序中我們寫:typedef structint num;int age;aaa,bbb,ccc;這算什么呢?我個人觀察編譯器(VC6)的理解,這相當于typedef structint num;int age;aaa;typed

11、ef aaa bbb;typedef aaa ccc;也就是說aaa,bbb,ccc三者都是結(jié)構(gòu)體類型。聲明變量時用任何一個都可以,在c+中也是如此。但是你要注意的是這個在c+中如果寫掉了typedef關(guān)鍵字,那么aaa,bbb,ccc將是截然不同的三個對象。第四篇:C/C+中typedef struct和struct的用法 struct _x1 .x1; 和 typedef struct _x2 . x2; 有什么不同? 其實, 前者是定義了類_x1和_x1的對象實例x1, 后者是定義了類_x2和_x2的類別名x2 , 所以它們在使用過程中是有取別的.請看實例1. 知識點 結(jié)構(gòu)也是一種數(shù)據(jù)類

12、型, 可以使用結(jié)構(gòu)變量, 因此, 象其它 類型的變量一樣, 在使用結(jié)構(gòu)變量時要先對其定義。 定義結(jié)構(gòu)變量的一般格式為: struct 結(jié)構(gòu)名 類型 變量名; 類型 變量名; . 結(jié)構(gòu)變量; 結(jié)構(gòu)名是結(jié)構(gòu)的標識符不是變量名。 另一種常用格式為: typedef struct 結(jié)構(gòu)名 類型 變量名; 類型 變量名; . 結(jié)構(gòu)別名; 另外注意: 在C中,struct不能包含函數(shù)。在C+中,對struct進行了擴展,可以包含函數(shù)。 = 實例1: struct.cpp #include <iostream> using namespace std; typedef struct _point

13、 int x; int y; point; /定義類,給類一個別名 struct _hello int x,y; hello; /同時定義類和對象 int main() point pt1; pt1.x = 2; pt1.y = 5; cout<< "ptpt1.x=" << pt1.x << "pt.y=" <<pt1.y <<endl; /hello pt2; /pt2.x = 8; /pt2.y =10; /cout<<"pt2pt2.x="<<

14、 pt2.x <<"pt2.y="<<pt2.y <<endl; /上面的hello pt2;這一行編譯將不能通過. 為什么? /因為hello是被定義了的對象實例了. /正確做法如下: 用hello.x和hello.y hello.x = 8; hello.y = 10; cout<< "hellohello.x=" << hello.x << "hello.y=" <<hello.y <<endl; return 0; 第五篇:問答 Q

15、: 用struct和typedef struct 定義一個結(jié)構(gòu)體有什么區(qū)別?為什么會有兩種方式呢?struct Student int a; stu; typedef struct Student2 int a; stu2; A: 事實上,這個東西是從C語言中遺留過來的,typedef可以定義新的復(fù)合類型或給現(xiàn)有類型起一個別名,在C語言中,如果你使用 struct xxx ; 的方法,使用時就必須用 struct xxx var 來聲明變量,而使用 typedef struct 的方法 就可以寫為 xxx var; 不過在C+中已經(jīng)沒有這回事了,無論你用哪一種寫法都可以使用第二種方式聲明變量,

16、這個應(yīng)該算是C語言的糟粕。用法小結(jié) 第一、四個用途 用途一: 定義一種類型的別名,而不只是簡單的宏替換??梢杂米魍瑫r聲明指針型的多個對象。比如:char* pa, pb; / 這多數(shù)不符合我們的意圖,它只聲明了一個指向字符變量的指針, / 和一個字符變量;以下則可行:typedef char* PCHAR; / 一般用大寫PCHAR pa, pb; / 可行,同時聲明了兩個指向字符變量的指針雖然:char *pa, *pb;也可行,但相對來說沒有用typedef的形式直觀,尤其在需要大量指針的地方,typedef的方式更省事。用途二: 用在舊的C的代碼中(具體多舊沒有查),幫助struct。以

17、前的代碼中,聲明struct新對象時,必須要帶上struct,即形式為: struct 結(jié)構(gòu)名 對象名,如:struct tagPOINT1int x;int y;struct tagPOINT1 p1; 而在C+中,則可以直接寫:結(jié)構(gòu)名 對象名,即:tagPOINT1 p1;估計某人覺得經(jīng)常多寫一個struct太麻煩了,于是就發(fā)明了:typedef struct tagPOINTint x;int y;POINT;POINT p1; / 這樣就比原來的方式少寫了一個struct,比較省事,尤其在大量使用的時候或許,在C+中,typedef的這種用途二不是很大,但是理解了它,對掌握以前的舊代碼

18、還是有幫助的,畢竟我們在項目中有可能會遇到較早些年代遺留下來的代碼。用途三: 用typedef來定義與平臺無關(guān)的類型。比如定義一個叫 REAL 的浮點類型,在目標平臺一上,讓它表示最高精度的類型為:typedef long double REAL; 在不支持 long double 的平臺二上,改為:typedef double REAL; 在連 double 都不支持的平臺三上,改為:typedef float REAL; 也就是說,當跨平臺時,只要改下 typedef 本身就行,不用對其他源碼做任何修改。標準庫就廣泛使用了這個技巧,比如size_t。另外,因為typedef是定義了一種類型

19、的新別名,不是簡單的字符串替換,所以它比宏來得穩(wěn)健(雖然用宏有時也可以完成以上的用途)。用途四: 為復(fù)雜的聲明定義一個新的簡單的別名。方法是:在原來的聲明里逐步用別名替換一部分復(fù)雜聲明,如此循環(huán),把帶變量名的部分留到最后替換,得到的就是原聲明的最簡化版。舉例:1. 原聲明:int *(*a5)(int, char*);變量名為a,直接用一個新別名pFun替換a就可以了:typedef int *(*pFun)(int, char*); 原聲明的最簡化版:pFun a5; 2. 原聲明:void (*b10) (void (*)();變量名為b,先替換右邊部分括號里的,pFunParam為別名一

20、:typedef void (*pFunParam)();再替換左邊的變量b,pFunx為別名二:typedef void (*pFunx)(pFunParam);原聲明的最簡化版:pFunx b10;3. 原聲明:doube(*)() (*e)9; 變量名為e,先替換左邊部分,pFuny為別名一:typedef double(*pFuny)();再替換右邊的變量e,pFunParamy為別名二typedef pFuny (*pFunParamy)9;原聲明的最簡化版:pFunParamy e; 理解復(fù)雜聲明可用的“右左法則”:從變量名看起,先往右,再往左,碰到一個圓括號就調(diào)轉(zhuǎn)閱讀的方向;括號

21、內(nèi)分析完就跳出括號,還是按先右后左的順序,如此循環(huán),直到整個聲明分析完。舉例:int (*func)(int *p);首先找到變量名func,外面有一對圓括號,而且左邊是一個*號,這說明func是一個指針;然后跳出這個圓括號,先看右邊,又遇到圓括號,這說明 (*func)是一個函數(shù),所以func是一個指向這類函數(shù)的指針,即函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值類型是int。int (*func5)(int *);func 右邊是一個運算符,說明func是具有5個元素的數(shù)組;func的左邊有一個*,說明func的元素是指針(注意這里的*不是修飾func,而是修飾 func5的,原因是運

22、算符優(yōu)先級比*高,func先跟結(jié)合)。跳出這個括號,看右邊,又遇到圓括號,說明func數(shù)組的元素是函數(shù)類型的指針,它指向的函數(shù)具有int*類型的形參,返回值類型為int。也可以記住2個模式:type (*)(.)函數(shù)指針 type (*)數(shù)組指針第二、兩大陷阱 陷阱一: 記住,typedef是定義了一種類型的新別名,不同于宏,它不是簡單的字符串替換。比如:先定義:typedef char* PSTR;然后:int mystrcmp(const PSTR, const PSTR);const PSTR實際上相當于const char*嗎?不是的,它實際上相當于char* const。原因在于co

23、nst給予了整個指針本身以常量性,也就是形成了常量指針char* const。簡單來說,記住當const和typedef一起出現(xiàn)時,typedef不會是簡單的字符串替換就行。陷阱二: typedef在語法上是一個存儲類的關(guān)鍵字(如auto、extern、mutable、static、register等一樣),雖然它并不真正影響對象的存儲特性,如:typedef static int INT2; /不可行編譯將失敗,會提示“指定了一個以上的存儲類”。以上資料出自: 作者:赤龍第三、typedef 與 #define的區(qū)別 案例一:通常講,typedef要比#define要好,特別是在有指針的場合

24、。請看例子:typedef char *pStr1;#define pStr2 char *;pStr1 s1, s2;pStr2 s3, s4;在上述的變量定義中,s1、s2、s3都被定義為char *,而s4則定義成了char,不是我們所預(yù)期的指針變量,根本原因就在于#define只是簡單的字符串替換而typedef則是為一個類型起新名字。案例二:下面的代碼中編譯器會報一個錯誤,你知道是哪個語句錯了嗎?typedef char * pStr;char string4 = "abc"const char *p1 = string;const pStr p2 = strin

25、g;p1+;p2+;是p2+出錯了。這個問題再一次提醒我們:typedef和#define不同,它不是簡單的文本替換。上述代碼中const pStr p2并不等于const char * p2。const pStr p2和const long x本質(zhì)上沒有區(qū)別,都是對變量進行只讀限制,只不過此處變量p2的數(shù)據(jù)類型是我們自己定義的而不是系統(tǒng)固有類型而已。因此,const pStr p2的含義是:限定數(shù)據(jù)類型為char *的變量p2為只讀,因此p2+錯誤。第四部分資料:使用 typedef 抑制劣質(zhì)代碼 摘要: Typedef 聲明有助于創(chuàng)建平臺無關(guān)類型,甚至能隱藏復(fù)雜和難以理解的語法。不管怎樣,

26、使用 typedef 能為代碼帶來意想不到的好處,通過本文你可以學(xué)習(xí)用 typedef 避免缺欠,從而使代碼更健壯。 typedef 聲明,簡稱 typedef,為現(xiàn)有類型創(chuàng)建一個新的名字。比如人們常常使用 typedef 來編寫更美觀和可讀的代碼。所謂美觀,意指 typedef 能隱藏笨拙的語法構(gòu)造以及平臺相關(guān)的數(shù)據(jù)類型,從而增強可移植性和以及未來的可維護性。本文下面將竭盡全力來揭示 typedef 強大功能以及如何避免一些常見的陷阱。Q:如何創(chuàng)建平臺無關(guān)的數(shù)據(jù)類型,隱藏笨拙且難以理解的語法?A: 使用 typedefs 為現(xiàn)有類型創(chuàng)建同義字。 定義易于記憶的類型名 typedef 使用最多

27、的地方是創(chuàng)建易于記憶的類型名,用它來歸檔程序員的意圖。類型出現(xiàn)在所聲明的變量名字中,位于 ''typedef'' 關(guān)鍵字右邊。例如:typedef int size;此聲明定義了一個 int 的同義字,名字為 size。注意 typedef 并不創(chuàng)建新的類型。它僅僅為現(xiàn)有類型添加一個同義字。你可以在任何需要 int 的上下文中使用 size:void measure(size * psz); size array4;size len = file.getlength();std:vector <size> vs; typedef 還可以掩飾符合類型,

28、如指針和數(shù)組。例如,你不用象下面這樣重復(fù)定義有 81 個字符元素的數(shù)組:char line81;char text81;定義一個 typedef,每當要用到相同類型和大小的數(shù)組時,可以這樣:typedef char Line81; Line text, secondline;getline(text);同樣,可以象下面這樣隱藏指針語法:typedef char * pstr;int mystrcmp(pstr, pstr);這里將帶我們到達第一個 typedef 陷阱。標準函數(shù) strcmp()有兩個const char *類型的參數(shù)。因此,它可能會誤導(dǎo)人們象下面這樣聲明 mystrcmp()

29、:int mystrcmp(const pstr, const pstr); 這是錯誤的,按照順序,const pstr被解釋為char * const(一個指向 char 的常量指針),而不是const char *(指向常量 char 的指針)。這個問題很容易解決:typedef const char * cpstr; int mystrcmp(cpstr, cpstr); / 現(xiàn)在是正確的記?。?不管什么時候,只要為指針聲明 typedef,那么都要在最終的 typedef 名稱中加一個 const,以使得該指針本身是常量,而不是對象。代碼簡化 上面討論的 typedef 行為有點像 #

30、define 宏,用其實際類型替代同義字。不同點是 typedef 在編譯時被解釋,因此讓編譯器來應(yīng)付超越預(yù)處理器能力的文本替換。例如:typedef int (*PF) (const char *, const char *);這個聲明引入了 PF 類型作為函數(shù)指針的同義字,該函數(shù)有兩個 const char * 類型的參數(shù)以及一個 int 類型的返回值。如果要使用下列形式的函數(shù)聲明,那么上述這個 typedef 是不可或缺的:PF Register(PF pf);Register() 的參數(shù)是一個 PF 類型的回調(diào)函數(shù),返回某個函數(shù)的地址,其署名與先前注冊的名字相同。做一次深呼吸。下面我展示一下如果不用 typedef,我們是如何實現(xiàn)這個聲明的:int (*Register (int (*pf)(const char *, const char *) (const char *, const char *); 很少有程序員理解它是什么意思,更不用說這種費解的代碼所帶來的出錯風(fēng)險了。顯然,這里使用 typedef 不

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論