• 【C进阶】之数据类型起别名( typedef )


    1 回顾定义定义的数据类型

    // 基本的数据类型
    int m_i;
    unsigned int m_ui;
    
    // 数组
    short m_arr1[2];
    unsigned int m_arr2[2][2];
    
    // 指针
    int *p;
    int **pp;
    
    // 指针数组/数组指针
    int *p_arr[2];
    int (*arr_p)[2];
    
    // 函数指针
    int (*func_p)(int, int);
    
    // 函数指针数组
    int (*func_p_arr[2])(int, int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2 定义变量的数据类型

    将变量名去除,剩余的就是你定义变量的数据类型

    // 基本的数据类型
    int ;
    unsigned int ;
    
    // 数组
    short [2];
    unsigned int [2][2];
    
    // 指针
    int *;
    int **;
    
    // 指针数组/数组指针
    int *[2];
    int (*)[2];
    
    // 函数指针
    int (*)(int, int);
    
    // 函数指针数组
    int (*[2])(int, int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3 使用新的数据类型定义变量

    将typedef写到定义变量的前边,此时变量名就是你的新定义的数据类型,可以使用新的数据类型定义变量

    typedef写到定义变量的前边,此时变量名就是你的新定义的数据类型,可以使用新的数据类型定义变量,
    
    // 基本的数据类型
    typedef int myint32_t;    // myint32_t是使用typedef对int类型起别名
    typedef unsigned int myuint32_t;  // myuint32_t是使用typedef对unsigned int类型起别名
    
    // 数组
    typedef short m_arr1_t[2];    // m_arr1_t是使用typedef对short [2]类型起别名
    typedef unsigned int m_arr2_t[2][2];  // m_arr12_t是使用typedef对unsigned int [2][2]类型起别名
    
    // 指针
    typedef int *p_t;  // p_t是使用typedef对int *类型起别名
    typedef int **pp_t;// pp_t是使用typedef对int **类型起别名
    
    // 指针数组/数组指针
    typedef int *p_arr_t[2];   // p_arr_t是使用typedef对int *[2]类型起别名
    typedef int (*arr_p_t)[2]; // arr_p_t是使用typedef对int (*)[2]类型起别名
    
    // 函数指针
    typedef int (*func_p_t)(int, int);  // func_p_t是使用typedef对int (*)(int, int)类型起别名
    
    // 函数指针数组
    typedef int (*func_p_arr_t[2])(int, int); 
    // func_p_arr_t是使用typedef对int (*[2])(int, int)类型起别名
    
    使用tppedef对数据类型起别名之后,使用别名定义变量和使用本身代表的类型定义变量一样一样。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4 参考案例

    #include 
    
    // 使用typedef对数据类型起别名
    
    // 基本的数据类型
    typedef int myint32_t;           // myint32_t是使用typedef对int类型起别名
    typedef unsigned int myuint32_t; // myuint32_t是使用typedef对unsigned int类型起别名
    
    // 数组
    typedef short m_arr1_t[2];           // m_arr1_t是使用typedef对short [2]类型起别名
    typedef unsigned int m_arr2_t[2][2]; // m_arr12_t是使用typedef对unsigned int [2][2]类型起别名
    
    // 指针
    typedef int *p_t;   // p_t是使用typedef对int *类型起别名
    typedef int **pp_t; // pp_t是使用typedef对int **类型起别名
    
    // 指针数组/数组指针
    typedef int *p_arr_t[2];   // p_arr_t是使用typedef对int *[2]类型起别名
    typedef int (*arr_p_t)[2]; // arr_p_t是使用typedef对int (*)[2]类型起别名
    
    // 函数指针
    typedef int (*func_p_t)(int, int); // func_p_t是使用typedef对int (*)(int, int)类型起别名
    
    // 函数指针数组
    typedef int (*func_p_arr_t[2])(int, int);
    // func_p_arr_t是使用typedef对int (*[2])(int, int)类型起别名
    
    int add(int a, int b)
    {
        return a + b;
    }
    int sub(int a, int b)
    {
        return a - b;
    }
    int main(int argc, const char *argv[])
    {
        /*your code*/
        // 基本类型  ----> 比较常见
        myint32_t a = 1000; // 等价于 int a = 1000;
    
        // 数组 ---> 基本不用
        m_arr1_t arr1 = {100, 200}; // 等价于short arr1[2]={100,200};
        m_arr2_t arr2 = {{100, 200}, {300, 400}};
        // 等价于 unsigned int arr2[2][2] = {{100,200},{300,400}};
    
        // 指针 ----> 基本不用
        p_t p = &a;   // 等价于int *p = &a;
        pp_t pp = &p; // 等价于 int **p = &p;
    
        // 指针数组/数组指针  ----> 偶尔使用
        p_arr_t p_arr = {&a, &a}; // 等价于 int *p_arr[2] = {&a, &a};
        int arr[2][2] = {{100, 200}, {300, 400}};
        arr_p_t arr_p = arr; // 等价于 int (*arr_p)[2] = arr;
    
        // 函数指针  ----> 经常使用
        func_p_t cal_p = add;  // 等价于 add;int (*cal_p)(int, int) =
        /*
            int calculator(int x, int y, int (*cal_p)(int,int))
            {
                return cal_p(x,y);
            }
    
            使用函数指针类型的别名:
            int calculator(int x, int y, func_p_t cal_p)
            {
                return cal_p(x,y);
            }
        */
    
        func_p_arr_t func_p_arr = {add,sub}; 
            // 等价于int (*func_p_arr[2])(int, int) = {add,sub};
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    5 typedef和#define的区别

    1. #define宏定义对数据类型起别名在预处理阶段展开;
      typedef对数据类型起别名参与到了编译的阶段;

    2. 使用typedef对数据类型起别名相当于重新定义了一个新的数据类型;
      宏定义就是在预处理阶段进行替换。

    3. 推荐使用typedef对数据类型起别名定义新的数据类型。

      #define  p_t   int *
      p_t p, q;  // int *p, q;   // p是int*类型,q是int类型。
      
      typedef int *p_t;
       p_t p, q;  // int *p, *q;   // p和q都是int*类型
      
      • 1
      • 2
      • 3
      • 4
      • 5
    4. 宏定义的结尾不允许出现分号,typedef的结尾必须加分号。

    6 typedef的陷阱

    陷阱一:

    记住,typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。比如先定义:

    typedef   char*   PSTR;
    
    • 1

    然后:

    int   mystrcmp(const   PSTR,   const   PSTR);
    
    • 1

    const PSTR实际上相当于const char*吗?

    不是的,它实际上相当于char* const。

    原因在于const给予了整个指针本身以常量性,也就是形成了常量指针char* const。

    简单来说,记住当const和typedef一起出现时,typedef不会是简单的字符串替换就行。

    陷阱二:

    typedef在语法上是一个存储类的关键字(如auto、extern、static、register等一样),虽然它并不真正影响对象的存储特性,如:

    typedef   static   int   INT2;   //不可行
    
    • 1

    编译将失败,会提示“指定了一个以上的存储类”。

  • 相关阅读:
    自学黑客(网络安全)
    Go并发编程基础
    Java入门项目——读书管理系统
    二叉树的前 中 后序的非递归实现(图文详解)
    关于GPU显卡的介绍
    systemui状态栏添加新图标
    Day17-购物车页面-收货地址-把address信息存储到vuex中
    Java+JSP基于ssm高校网上教材征订系统-计算机毕业设计
    【残差网络 论文泛读】……DenseNet……(Densely Connected Convolutional Networks)
    服务器连接校园网
  • 原文地址:https://blog.csdn.net/distant_Rove666/article/details/127663521