C語言基礎-15-typedef

這講介紹C語言中很經常使用的一個關鍵字---typedefhtml

1、typedef做用簡介

* 咱們可使用typedef關鍵字爲各類數據類型定義一個新名字(別名)。ios

#include <stdio.h>

typedef int Integer;
typedef unsigned int UInterger;

typedef float Float;

int main(int argc, const char * argv[]) {
    Integer i = -10;
    UInterger ui = 11;
    
    Float f = 12.39f;
    
    printf("%d  %d  %.2f", i, ui, f);
    
    return 0;
}


在第三、第四、第6行分別給int、unsigned int、float起了個別名,而後在main函數中使用別名定義變量,用來跟原來的基本類型是徹底同樣的。輸出結果:spring

固然,給類型起別名後,原來的int、float仍是能夠正常使用的:函數

int i = 10;
float f = 10.0f;

 

* 也能夠在別名的基礎上再起一個別名ui

typedef int Integer;
typedef Integer MyInteger;

 

2、typedef與指針

除開能夠給基本數據類型起別名,typedef也能夠給指針起別名spa

#include <stdio.h>

typedef char *String;

int main(int argc, const char * argv[]) {
    // 至關於char *str = "This is a string!";
    String str = "This is a string!";
    
    printf("%s", str);
    
    return 0;
}

在第3給指針類型char *起別名爲String,而後在第7行使用String定義了一個字符串,是否是有點Java的感受?指針

3、typedef與結構體

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

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

// 定義一個結構體
struct MyPoint{
  float x;
  float y;
};

int main(int argc, const char *arg[]){
  // 定義結構體的變量
  struct MyPoint p;
  p.x = 10.0f;
  p.y = 20.2f;
  
  return 0;
  }

默認狀況下,咱們定義結構體變量須要帶個struct關鍵字,看第9行orm

2.使用typedef給結構體起別名

// 定義一個結構體
struct MyPoint {
    float x;
    float y;
};

// 起別名
typedef struct MyPoint Point;

int main(int argc, const char * argv[]) {
    // 定義結構體變量
    Point p;
    p.x = 10.0f;
    p.y = 20.0f;
    
    return 0;
}

咱們在第8行給結構體MyPoint起了個別名叫作Point,而後在12行使用Point定義了一個結構體變量p,不用再帶上struct關鍵字了htm

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


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

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

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

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

typedef能夠給指針、結構體起別名,固然也能夠給指向結構體的指針起別名

#include <stdio.h>

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

// 起別名
typedef Point *PP;

int main(int argc, const char * argv[]) {
    // 定義結構體變量
    Point point = {10, 20};
    
    // 定義指針變量
    PP p = &point;
    
    // 利用指針變量訪問結構體成員
    printf("x=%f,y=%f", p->x, p->y);
    return 0;
}

在第4行定義了一個結構體,順便起了個別名叫Point,第10行爲指向結構體的指針定義了別名PP。而後在main函數中使用這2個別名。

輸出結果:


4、typedef與枚舉類型

使用typedef給枚舉類型起別名也可使代碼簡潔。

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

int main(int argc, const char * argv[]) {
    // 定義枚舉變量
    Season s = spring;
    
    return 0;
}

在第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.先來回顧下函數指針的知識

#include <stdio.h>

// 定義一個sum函數,計算a跟b的和
int sum(int a, int b) {
    int c = a + b;
    printf("%d + %d = %d", a, b, c);
    return c;
}

int main(int argc, const char * argv[]) {
    // 定義一個指向sum函數的指針變量p
    int (*p)(int, int) = sum;
    
    // 利用指針變量p調用sum函數
    (*p)(4, 5);
    
    return 0;
}

 在第4行定義了一個sum函數,第12行定義了一個指向sum函數的指針變量p,能夠發現,這個指針變量p的定義比通常的指針變量看來複雜多了,不利於理解。

* 第15行調用了p指向的sum函數,輸出結果:

 

2.爲了簡化代碼和方便理解,咱們可使用typedef給指向函數的指針類型起別名

#include <stdio.h>

// 定義一個sum函數,計算a跟b的和
int sum(int a, int b) {
    int c = a + b;
    printf("%d + %d = %d", a, b, c);
    return c;
}

typedef int (*MySum)(int, int);

int main(int argc, const char * argv[]) {
    // 定義一個指向sum函數的指針變量p
    MySum p = sum;
    
    // 利用指針變量p調用sum函數
    (*p)(4, 5);
    
    return 0;
}

* 看第10行,意思是:給指向函數的指針類型,起了個別名叫MySum,被指向的函數接收2個int類型的參數,返回值爲int類型。

* 在第14行直接用別名MySum定義一個指向sum函數的指針變量p,這樣看起來簡單舒服多了。第17行的函數調用是同樣的。

 

6、typedef與#define

1.先來看看下面的兩段代碼有什麼區別(注意每一段的第1行代碼)

* 第1段

typedef char *String;

int main(int argc, const char * argv[]) {
    String str = "This is a string!";
    return 0;
}
#define String char *

int main(int argc, const char * argv[]) {
    String str = "This is a string!";
    return 0;
}

上面的兩段代碼只是第1行代碼不同,運行的效果都是同樣的:定義了一個字符串"This is a string!"

但它們的實現方式是不同的:

  • 第1段代碼是用typedefchar *定義別名爲String

  • 第2段代碼是用char *代替代碼中的宏名String

只看上面兩段代碼,彷佛看不太出typedef#define的區別。

2.再來看一段代碼

typedef char *String1;

#define String2 char *

int main(int argc, const char * argv[]) {
    String1 str1, str2;
    
    String2 str3, str4;
    return 0;
}

第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


注:本文轉自M了個J的博客。

相關文章
相關標籤/搜索