C學習-typedef-給數據類型起別名(十)

1、typedef做用簡介

咱們可使用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;

2、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的感受?code

3、typedef與結構體

給結構體起別名可使代碼更加簡潔明ip

1.默認狀況下結構體變量的使用

// 定義一個結構體
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關鍵字字符串

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關鍵字了string

其實第1~第8行的代碼能夠簡寫爲:it

// 定義一個結構體,順便起別名
typedef struct MyPoint {
    float x;
    float y;
} Point;

甚至能夠省略結構體名稱:

typedef struct {
    float x;
    float y;
} Point;

3、typedef與指向結構體的指針

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個別名。
輸出結果爲:clipboard.png

4、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關鍵字了。

第1行~第4行代碼能夠簡化爲:

// 定義枚舉類型,而且起別名
typedef enum Season {spring, summer, autumn, winter} Season

甚至能夠省略枚舉名稱,簡化爲:

typedef enum {spring, summer, autumn, winter} Season;

5、typedef與指向函數的指針

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函數,輸出結果:4 + 5 = 9

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行的函數調用是同樣的。

6、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段代碼是用typedefchar *定義別名爲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

相關文章
相關標籤/搜索