咱們可使用typedef
關鍵字爲各類數據類型定義一個新名字(別名)
。spring
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 }
在第三、第四、第6行分別給int、unsigned int、float起了個別名,而後在main函數中使用別名定義變量,用來跟原來的基本類型是徹底同樣的。輸出結果:
-10 11 12.39函數
固然,給類型起別名後,原來的int、float仍是能夠正常使用的:ui
int i = 10; float f = 10.0f;
也能夠在別名的基礎上再起一個別名spa
typedef int Integer; typedef Integer MyInteger;
除開能夠給基本數據類型起別名,typedef也能夠給指針起別名指針
1 #include <stdio.h> 2 3 typedef char *String; 4 5 int main(int argc, const char * argv[]) { 6 // 至關於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
定義了一個字符串,是否是有點Java的感受?code
給結構體起別名可使代碼更加簡潔明ip
// 定義一個結構體 struct MyPoint { float x; float y; }; int main(int argc, const char * argv[]) { // 定義結構體變量 struct MyPoint p; p.x = 10.0f; p.y = 20.0f; return 0; }
默認狀況下,咱們定義結構體變量須要帶個struct
關鍵字字符串
1 // 定義一個結構體 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 // 定義結構體變量 12 Point p; 13 p.x = 10.0f; 14 p.y = 20.0f; 15 16 return 0; 17 }
咱們在第8行給結構體MyPoint
起了個別名叫作Point
,而後在12行使用Point
定義了一個結構體變量p
,不用再帶上struct關鍵字了string
其實第1~第8行的代碼能夠簡寫爲:it
// 定義一個結構體,順便起別名 typedef struct MyPoint { float x; float y; } Point;
甚至能夠省略結構體名稱:
typedef struct { float x; float y; } Point;
typedef
能夠給指針、結構體起別名,固然也能夠給指向結構體的指針起別名
1 #include <stdio.h> 2 3 // 定義一個結構體並起別名 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 // 定義結構體變量 14 Point point = {10, 20}; 15 16 // 定義指針變量 17 PP p = &point; 18 19 // 利用指針變量訪問結構體成員 20 printf("x=%f,y=%f", p->x, p->y); 21 return 0; 22 }
在第4行定義了一個結構體,順便起了個別名叫Point
,第10行爲指向結構體的指針定義了別名PP
。而後在main函數中使用這2個別名。
輸出結果爲:
使用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關鍵字了。
第1行~第4行代碼能夠簡化爲:
// 定義枚舉類型,而且起別名 typedef enum Season {spring, summer, autumn, winter} Season
甚至能夠省略枚舉名稱,簡化爲:
typedef enum {spring, summer, autumn, winter} Season;
1 #include <stdio.h> 2 3 // 定義一個sum函數,計算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函數的指針變量p 12 int (*p)(int, int) = sum; 13 14 // 利用指針變量p調用sum函數 15 (*p)(4, 5); 16 17 return 0; 18 }
在第4行定義了一個sum函數,第12行定義了一個指向sum函數的指針變量p,能夠發現,這個指針變量p的定義比通常的指針變量看來複雜多了,不利於理解。
第15行調用了p指向的sum函數,輸出結果:4 + 5 = 9
1 #include <stdio.h> 2 3 // 定義一個sum函數,計算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函數的指針變量p 14 MySum p = sum; 15 16 // 利用指針變量p調用sum函數 17 (*p)(4, 5); 18 19 return 0; 20 }
看第10行,意思是:給指向函數的指針類型,起了個別名叫MySum
,被指向的函數接收2個int類型的參數,返回值爲int類型。
在第14行直接用別名MySum
定義一個指向sum函數的指針變量p,這樣看起來簡單舒服多了。第17行的函數調用是同樣的。
1.先來看看下面的兩段代碼有什麼區別(注意每一段的第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行代碼不同,運行的效果都是同樣的:定義了一個字符串"This is a string!"。
但它們的實現方式是不同的:
第1段代碼是用typedef
給char *
定義別名爲String
第2段代碼是用char *
代替代碼中的宏名String
只看上面兩段代碼,彷佛看不太出typedef
和#define
的區別。
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。而後在第六、第8行定義了4個變量。
重點來了,注意:在這種狀況下,只有str一、str二、str3纔是指向char類型的指針變量
,str4只是個char類型的變量
。
下面簡單分析一下緣由:
若是連續聲明兩個int類型的變量,咱們能夠這樣寫:
int a, b;
上面的代碼至關於:
int a; int b;
以此類推
1 typedef char *String1; 2 3 String1 str1, str2;
通過typedef處理後,String1也算是一種數據類型,因此第3行代碼至關於
1 String1 str1; 2 String1 str2;
因爲String1就是char *,因此上面的兩行代碼等於
char *str1; char *str2;
再看看宏定義的狀況
1 #define String2 char * 2 3 String2 str3, str4;
由於宏定義純粹是字符串替換,用char *代替String2,因此第3行代碼至關於
char * str3, str4;
其實也就至關於:
char * str3; char str4;
能夠看出,只有str4是基本數據類型,str一、str二、str3都是指針類型。
因此,之後給類型起別名,最好使用
typedef
,而不是使用#define