学习笔记之23-typedef
一、typedef作用簡介
* 我們可以使用typedef關(guān)鍵字為各種數(shù)據(jù)類型定義一個新名字(別名)。
1 #include <stdio.h> 2 3 typedef int Integer; 4 typedef unsigned int UInterger; 5 6 typedef float Float; 7 8 int main(int argc, const char * argv[]) { 9 Integer i = -10; 10 UInterger ui = 11; 11 12 Float f = 12.39f; 13 14 printf("%d %d %.2f", i, ui, f); 15 16 return 0; 17 }?在第3、第4、第6行分別給int、unsigned int、float起了個別名,然后在main函數(shù)中使用別名定義變量,用來跟原來的基本類型是完全一樣的。輸出結(jié)果:
當(dāng)然,給類型起別名后,原來的int、float還是可以正常使用的:
int i = 10;float f = 10.0f;?
* 也可以在別名的基礎(chǔ)上再起一個別名
typedef int Integer;typedef Integer MyInteger;?
二、typedef與指針
除開可以給基本數(shù)據(jù)類型起別名,typedef也可以給指針起別名
1 #include <stdio.h> 2 3 typedef char *String; 4 5 int main(int argc, const char * argv[]) { 6 // 相當(dāng)于char *str = "This is a string!"; 7 String str = "This is a string!"; 8 9 printf("%s", str); 10 11 return 0; 12 }在第3給指針類型char *起別名為String,然后在第7行使用String定義了一個字符串,是不是有點(diǎn)Java的感覺?
?
三、typedef與結(jié)構(gòu)體
給結(jié)構(gòu)體起別名可以使代碼更加簡潔明
1.默認(rèn)情況下結(jié)構(gòu)體變量的使用
1 // 定義一個結(jié)構(gòu)體 2 struct MyPoint { 3 float x; 4 float y; 5 }; 6 7 int main(int argc, const char * argv[]) { 8 // 定義結(jié)構(gòu)體變量 9 struct MyPoint p; 10 p.x = 10.0f; 11 p.y = 20.0f; 12 13 return 0; 14 }默認(rèn)情況下,我們定義結(jié)構(gòu)體變量需要帶個struct關(guān)鍵字,看第9行
2.使用typedef給結(jié)構(gòu)體起別名
1 // 定義一個結(jié)構(gòu)體 2 struct MyPoint { 3 float x; 4 float y; 5 }; 6 7 // 起別名 8 typedef struct MyPoint Point; 9 10 int main(int argc, const char * argv[]) { 11 // 定義結(jié)構(gòu)體變量 12 Point p; 13 p.x = 10.0f; 14 p.y = 20.0f; 15 16 return 0; 17 }我們在第8行給結(jié)構(gòu)體MyPoint起了個別名叫做Point,然后在12行使用Point定義了一個結(jié)構(gòu)體變量p,不用再帶上struct關(guān)鍵字了
其實(shí)第1~第8行的代碼可以簡寫為:
// 定義一個結(jié)構(gòu)體,順便起別名 typedef struct MyPoint { float x; float y; } Point;甚至可以省略結(jié)構(gòu)體名稱:
typedef struct {float x;float y; } Point;?
三、typedef與指向結(jié)構(gòu)體的指針
typedef可以給指針、結(jié)構(gòu)體起別名,當(dāng)然也可以給指向結(jié)構(gòu)體的指針起別名
1 #include <stdio.h> 2 3 // 定義一個結(jié)構(gòu)體并起別名 4 typedef struct { 5 float x; 6 float y; 7 } Point; 8 9 // 起別名 10 typedef Point *PP; 11 12 int main(int argc, const char * argv[]) { 13 // 定義結(jié)構(gòu)體變量 14 Point point = {10, 20}; 15 16 // 定義指針變量 17 PP p = &point; 18 19 // 利用指針變量訪問結(jié)構(gòu)體成員 20 printf("x=%f,y=%f", p->x, p->y); 21 return 0; 22 }在第4行定義了一個結(jié)構(gòu)體,順便起了個別名叫Point,第10行為指向結(jié)構(gòu)體的指針定義了別名PP。然后在main函數(shù)中使用這2個別名。
輸出結(jié)果:
?
四、typedef與枚舉類型
使用typedef給枚舉類型起別名也可以使代碼簡潔。
1 // 定義枚舉類型 2 enum Season {spring, summer, autumn, winter}; 3 // 給枚舉類型起別名 4 typedef enum Season Season; 5 6 int main(int argc, const char * argv[]) { 7 // 定義枚舉變量 8 Season s = spring; 9 10 return 0; 11 }在第2行定義了枚舉類型,在第4行起了別名為Season,然后在第8行直接使用別名定義枚舉變量,不用再帶上enum關(guān)鍵字了。
第1行~第4行代碼可以簡化為:
// 定義枚舉類型,并且起別名 typedef enum Season {spring, summer, autumn, winter} Season?甚至可以省略枚舉名稱,簡化為:
typedef enum {spring, summer, autumn, winter} Season;五、typedef與指向函數(shù)的指針
1.先來回顧下函數(shù)指針的知識
1 #include <stdio.h> 2 3 // 定義一個sum函數(shù),計(jì)算a跟b的和 4 int sum(int a, int b) { 5 int c = a + b; 6 printf("%d + %d = %d", a, b, c); 7 return c; 8 } 9 10 int main(int argc, const char * argv[]) { 11 // 定義一個指向sum函數(shù)的指針變量p 12 int (*p)(int, int) = sum; 13 14 // 利用指針變量p調(diào)用sum函數(shù) 15 (*p)(4, 5); 16 17 return 0; 18 }* 在第4行定義了一個sum函數(shù),第12行定義了一個指向sum函數(shù)的指針變量p,可以發(fā)現(xiàn),這個指針變量p的定義比一般的指針變量看來復(fù)雜多了,不利于理解。
* 第15行調(diào)用了p指向的sum函數(shù),輸出結(jié)果:
?
2.為了簡化代碼和方便理解,我們可以使用typedef給指向函數(shù)的指針類型起別名
1 #include <stdio.h> 2 3 // 定義一個sum函數(shù),計(jì)算a跟b的和 4 int sum(int a, int b) { 5 int c = a + b; 6 printf("%d + %d = %d", a, b, c); 7 return c; 8 } 9 10 typedef int (*MySum)(int, int); 11 12 int main(int argc, const char * argv[]) { 13 // 定義一個指向sum函數(shù)的指針變量p 14 MySum p = sum; 15 16 // 利用指針變量p調(diào)用sum函數(shù) 17 (*p)(4, 5); 18 19 return 0; 20 }* 看第10行,意思是:給指向函數(shù)的指針類型,起了個別名叫MySum,被指向的函數(shù)接收2個int類型的參數(shù),返回值為int類型。
* 在第14行直接用別名MySum定義一個指向sum函數(shù)的指針變量p,這樣看起來簡單舒服多了。第17行的函數(shù)調(diào)用是一樣的。
?
六、typedef與#define
1.先來看看下面的兩段代碼有什么區(qū)別(注意每一段的第1行代碼)
* 第1段
1 typedef char *String; 2 3 int main(int argc, const char * argv[]) { 4 String str = "This is a string!"; 5 return 0; 6 }* 第2段
1 #define String char * 2 3 int main(int argc, const char * argv[]) { 4 String str = "This is a string!"; 5 return 0; 6 }上面的兩段代碼只是第1行代碼不一樣,運(yùn)行的效果都是一樣的:定義了一個字符串"This is a string!"。
但它們的實(shí)現(xiàn)方式是不一樣的:
- 第1段代碼是用typedef給char *定義別名為String
- 第2段代碼是用char *代替代碼中的宏名String
只看上面兩段代碼,似乎看不太出typedef和#define的區(qū)別。
?
2.再來看一段代碼
1 typedef char *String1; 2 3 #define String2 char * 4 5 int main(int argc, const char * argv[]) { 6 String1 str1, str2; 7 8 String2 str3, str4; 9 return 0; 10 }第1行給char *起了個別名String1,第2行定義了宏String2。然后在第6、第8行定義了4個變量。
重點(diǎn)來了,注意:在這種情況下,只有str1、str2、str3才是指向char類型的指針變量,str4只是個char類型的變量。
?
下面簡單分析一下原因:
* 如果連續(xù)聲明兩個int類型的變量,我們可以這樣寫:
int a, b;上面的代碼相當(dāng)于:
int a; int b;* 以此類推
1 typedef char *String1; 2 3 String1 str1, str2;經(jīng)過typedef處理后,String1也算是一種數(shù)據(jù)類型,所以第3行代碼相當(dāng)于
1 String1 str1; 2 String1 str2;由于String1就是char *,所以上面的兩行代碼等于
char *str1; char *str2;?
* 再看看宏定義的情況
1 #define String2 char * 2 3 String2 str3, str4;因?yàn)楹甓x純粹是字符串替換,用char *代替String2,所以第3行代碼相當(dāng)于
char * str3, str4;其實(shí)也就相當(dāng)于:
char * str3; char str4;可以看出,只有str4是基本數(shù)據(jù)類型,str1、str2、str3都是指針類型。
所以,以后給類型起別名,最好使用typedef,而不是使用#define
?
轉(zhuǎn)載于:https://www.cnblogs.com/tlios/p/4070533.html
總結(jié)
以上是生活随笔為你收集整理的学习笔记之23-typedef的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu下配置Apache的Work
- 下一篇: MapReduce:Job性能调优总结