本文目錄
- [一、typedef作用簡介](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label0)
- [二、typedef與指針](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label1)
- [三、typedef與結構體](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label2)
- [三、typedef與指向結構體的指針](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label3)
- [四、typedef與枚舉類型](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label4)
- [五、typedef與指向函數的指針](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label5)
- [六、typedef與#define](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#label6)
說明:這個C語言專題,是學習iOS開發的前奏。也為了讓有面向對象語言開發經驗的程序員,能夠快速上手C語言。如果你還沒有編程經驗,或者對C語言、iOS開發不感興趣,請忽略
這講介紹C語言中很常用的一個關鍵字---typedef。
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 一、typedef作用簡介
* 我們可以使用typedef關鍵字為各種數據類型定義一個新名字(別名)。
~~~
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函數中使用別名定義變量,用來跟原來的基本類型是完全一樣的。輸出結果:
當然,給類型起別名后,原來的int、float還是可以正常使用的:
~~~
int i = 10;
float f = 10.0f;
~~~
* 也可以在別名的基礎上再起一個別名
~~~
typedef int Integer;
typedef Integer MyInteger;
~~~
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 二、typedef與指針
除開可以給基本數據類型起別名,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的感覺?
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 三、typedef與[結構體](http://www.cnblogs.com/mjios/archive/2013/03/24/2977910.html)
給結構體起別名可以使代碼更加簡潔明
### 1.默認情況下結構體變量的使用
~~~
1 // 定義一個結構體
2 struct MyPoint {
3 float x;
4 float y;
5 };
6
7 int main(int argc, const char * argv[]) {
8 // 定義結構體變量
9 struct MyPoint p;
10 p.x = 10.0f;
11 p.y = 20.0f;
12
13 return 0;
14 }
~~~
默認情況下,我們定義結構體變量需要帶個struct關鍵字,看第9行
### 2.使用typedef給結構體起別名
~~~
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關鍵字了
其實第1~第8行的代碼可以簡寫為:
~~~
// 定義一個結構體,順便起別名
typedef struct MyPoint {
float x;
float y;
} Point;
~~~
甚至可以省略結構體名稱:
~~~
typedef struct {
float x;
float y;
} Point;
~~~
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 三、typedef與指向[結構體](http://www.cnblogs.com/mjios/archive/2013/03/24/2977910.html)的指針
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個別名。
輸出結果:
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 四、typedef與[枚舉類型](http://www.cnblogs.com/mjios/archive/2013/03/24/2979390.html)
使用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;
~~~
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 五、typedef與[指向函數的指針](http://www.cnblogs.com/mjios/archive/2013/03/19/2967037.html)
1.先來回顧下函數指針的知識
~~~
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函數,輸出結果:
2.為了簡化代碼和方便理解,我們可以使用typedef給指向函數的指針類型起別名
~~~
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行的函數調用是一樣的。
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/24/2979482.html#labelTop)
### 六、typedef與#define
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。然后在第6、第8行定義了4個變量。
重點來了,注意:在這種情況下,只有str1、str2、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是基本數據類型,str1、str2、str3都是指針類型。
所以,以后給類型起別名,最好使用typedef,而不是使用#define
- 前言
- C語言入門教程1-概述
- C語言入門教程2-第一個C程序
- C語言入門教程3-關鍵字、標識符、注釋
- C語言入門教程4-變量與常量
- C語言入門教程5-進制
- C語言入門教程6-變量與內存
- C語言入門教程7-基本數據類型
- C語言入門教程8-運算符
- C語言入門教程9-流程控制
- C語言入門教程10-函數
- C語言入門教程11-函數的聲明定義
- C語言入門教程12-scanf與printf輸入輸出函數
- C語言入門教程13-數組-批量數據存儲
- C語言入門教程14-字符串
- C語言入門教程15-字符與字符串常用處理函數
- C語言入門教程16-指針
- C語言入門教程17-指向一維數組元素的指針
- C語言入門教程18-指針與字符串
- C語言入門教程19-預處理指令1-宏定義
- C語言入門教程20-預處理指令2-條件編譯
- C語言入門教程21-預處理指令3-文件包含
- C語言入門教程22-變量類型與作用域
- C語言入門教程23-枚舉
- C語言入門教程24-結構體
- C語言入門教程25-typedef類型別名