typedef的應用

一、與typedef相關的預備知識

1.1 C語言的兩種類型

  1. 內建類型ADT(也叫原生類型、基礎數據類型):編譯器自帶的類型,如int/double
  2. 自定義類型UDT:不是編譯器自帶的類型,是程序員自己定義的,如結構體類型、數組類型、函數指針類型等

1.2 typedef加工的是類型而不是變量

  • 類型就是一個數據模板,變量是一個實在的數據
  • 類型是不佔內存的,變量是佔內存的
  • 在面向對象的語言中,類型就是類class,變量就是對象
  • typedef不新建類型,只是對現有的類型進行重命名

二、typedef#define宏的區別

2.1 原理不同

  • typedef是關鍵字,它在自己的作用域內給一個已經存在的類型一個別名,在編譯時處理,有類型檢查功能。
  • #defineC語言中的宏定義,是預處理指令,在預處理時進行簡單而機械的字符串替換,不作正確性檢查

2.2 功能不同

  • typedef用來定義類型的別名,方便使用
  • #define除爲類型重命名外,還可以定義常量、變量、簡化複雜運算

2.3 對指針的操縱範圍不同

2.3.1 測試代碼

typedef char* pChar1;
#define pChar2 char*

int main(void)
{
    pChar1 c1, c2;
    pChar2 c3, c4;
    char* p;
    p = c1;
    p = c2;
    p = c3;
    p = c4;
    return 0;
}

2.3.2 測試結果

1u8hDK.png

我們可以看到,在p = c4處有警告:

warning: assignment makes pointer from integer without a cast

即:警告:在沒有強制轉換的情況下將整數值賦給指針

也就是說c4其實只是一個char型變量而c2不是!!!

三、typedef與結構體

3.1 結構體在使用時的常規步驟:

  1. 先定義結構體的類型
  2. 結構體的類型去定義變量
  3. 使用結構體成員
/*定義結構體類型,不佔內存*/
struct student
{
    char name[20];
    int age;
    char sex[10];
};

int main(void)
{
    struct student s1;
    //struct student是類型,不佔內存;s1是變量,佔內存
    s1.age = 20;//結構體成員的使用
}

3.2 typedef簡化變量定義

C語言語法規定,結構體使用時必須是struct 結構體類型名 結構體變量名的形式,如果需要大量使用結構體,這樣略爲麻煩,可以使用typedef來簡化,如:

typedef struct student
{
    char name[20];
    int age;
    char sex[10];
}student_t;

這時就一下定義了兩個類型名:struct studentstudent_t
也就是說struct student s1;就可以簡化定義爲student_t s1

在很多情況下,會直接簡化爲:

typedef struct student
{
    char name[20];
    int age;
    char sex[10];
}student;

同時使用兩個studentC語言中是允許的,這也同時定義了兩個類型名:
struct studentstudent

在結構體的定義時,也可以同時定義兩個類型,如下所示:

typedef struct student
{
    char name[20];
    int age;
    char sex[10];
}student, *pStudent;

在這裏面,第一個是結構體類型,有兩個類型名:struct studentstudent
第二個是結構體指針類型:有兩個類型名:struct student *pStudent

測試代碼:

int main(void)
{
    student s1;
    s1.age = 20;
    pStudent p1 = &s1;
    printf("student s1 age = %d\n", p1 -> age);
    return 0;
}

測試結果:

四、typedefconst

4.1 代碼段1

typedef int* PINT;
const PINT p;

相當於是 int *const p;
也就是說p是不可變的,p指向的變量是可變的

4.2 代碼段2

typedef int* PINT;
PINT const p;

也相當於是 int *const p;

4.3 如果想得到const int *p;

typedef const int *CPINT;
CPINT p;

4.4 測試代碼:

#include <stdio.h>

typedef int *PINT;
typedef const int *CPINT;

int main(void)
{
    int arr[2] = {1, 2};
    /*指向的初始地址*/
    const PINT p0 = &arr[0];
    PINT const p1 = &arr[0];
    CPINT p2 = &arr[0];
    /*嘗試改變指向的地址*/
    p0 = &arr[1];
    p1 = &arr[1];
    p2 = &arr[1];
    /*嘗試改變指向的變量*/
    *p0 = arr[1];
    *p1 = arr[1];
    *p2 = arr[1];

    return 0;
}

4.5 編譯結果:

1usJ1K.png

我們可以看到編譯時報了三個error:

4.5typedef.c:52:8: error: assignment of read-only variable ‘p0’
     p0 = &arr[1];
        ^
4.5typedef.c:53:8: error: assignment of read-only variable ‘p1’
     p1 = &arr[1];
        ^
4.5typedef.c:58:9: error: assignment of read-only location ‘*p2’
     *p2 = arr[1];
         ^

p0、p1、*p2都是隻讀的,也就應證了前面所說的三個代碼段。

五、typedef與函數指針

c標準庫中的strcpy函數:
char *strcpy(char *dest, const char *src);

定義三個指向該函數的函數指針:

char * (*p1) (char *, const char *);
char * (*p2) (char *, const char *);
char * (*p3) (char *, const char *);

使用typedef來簡化:

typedef char * (*pFunc) (char *, const char *);
pFunc p1, p2, p3;

其中,typedef重命名了一個類型,這個類型新名字叫pFunc
類型是:char * (*) (char *, const char *);

六、使用typedef的意義

  1. 簡化類型的描述
  2. 創造平臺無關類型
    在很多編程體系下,人們傾向於不使用int、double等這些與平臺相關的平臺內建類型(int32位機上是32位的,64位機上是64位的)。爲了解決這個問題,很多程序使用自定義的中間類型來緩衝。比如:
/*自定義中間類型來做緩衝*/
typedef int sizet_32;
typedef int lent_64;
typedef volatile unsigned int vn32;
/*使用自定義類型來定義變量*/
sizet_32 a;
lent_64 b;
vn32 c;
發佈了37 篇原創文章 · 獲贊 3 · 訪問量 5374
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章