技术交流QQ群:1027579432,欢迎你的加入!

1.typedef用法详解

  • C++中允许为一个数据类型起一个“别名”,就像给别人起一个绰号一样。起别名的目的不是为了提高程序运行效率,而是为了编码方便。例如有一个结构体的名字是stu,要想定义一个结构体变量就得这样写:
        struct stu student1;
    
  • struct看上去多余的,但不写就会报错。如果为struct stu起一个别名STU,书写起来就很很方便:
    STU student1;
    
  • 这种写法更加简练,意义也非常明确,不管是在标准头文件中还是以后的编程实践中,都会大量使用这种别名。使用关键字typedef可以为类型起一个新的别名。typedef的用法一般为:
    typedef 旧名字 新名字;
    
  • oldName是类型原来的名字,newName是类型新的名字。例如:
        typedef int INT;
        INT a, b;
        a = 100;
        b = 1000;
    
  • typedef还可以给数组、指针、结构体等类型定义别名。先看一个给数组类型定义别名的例子:
    typedef char ARRAY20[20];
    
  • 表示ARRAY20是类型char [20]的别名,它是一个长度为20的数据类型,接着可以使用ARRAY20定义数组:
        ARRAY20 a1, a2, s1, s2;  // 等价于 char a1[20]; char a2[20]; char s1[20]; char s2[20];
    
  • 还可以为结构体类型定义别名:
        typedef struct stu{
            char name[20];
            int age;
            char address[20];
        }STU;
    
  • STU是struct stu的别名,可以使用STU定义结构体变量,例如:
        STU student1, student2;  // 等价于 struct stu student1, student2;
    
  • 也可以为指针类型定义别名,例如:
        typedef int (*PTR_TO_ARR)[4];
    
  • 表示PTR_TO_ARR是类型int *[4]的别名,接着可以使用PTR_TO_ARR定义数组指针:
        PTR_TO_ARR p1, p2;  // 等价于 int (*p1)[4];  int (*p2)[4];
    
  • 按照类似的写法,可以为函数指针类型定义别名:
        typedef int (*PTR_TO_FUN)(int, int); 
        PTR_TO_FUN pfunc;    // 等价于 int (*pfunc)(int, int);   // 函数指针
    
  • 为指针定义别名实例如下:
        #include "iostream"
    
        using namespace std;
    
        #define  MAXSIZE 30
    
        // 为基本类型定义类型的别名
        typedef int INT;
        INT aa;
        // 为数组类型定义类型的别名
        typedef int ARRAY[20];
        ARRAY a1;  // 等价于int a1[20];
        // 为结构体类型定义类型别名
        typedef struct stu{
            char name[MAXSIZE];
            int age;
            char address[MAXSIZE];
        }STU;
    
        STU student1;  // 等价于struct stu student1;
    
        // 为指针类型定义类型别名
        typedef int (*PTR_TO_ARRAY)[MAXSIZE];
    
        PTR_TO_ARRAY b1;  // 等价于 int (*b1)[MAXSIZE];  定义一个数组指针
    
        typedef float (*PTR_TO_FUNC)(INT, float);
    
        PTR_TO_FUNC func;  // 等价于 float (*func)(int, float);  // 定义一个函数指针
    
    
        typedef char (*ptr_array)[30];  // 数组指针
        typedef INT (*ptr_func)(INT, INT);  // 函数指针
    
        int max(int a, int b){
            return a > b? a:b;
        }
    
        char str[3][30] = {
            "https://www.baidu.com",
            "百度",
            "baidu"
        };
    
        int main(){
        ptr_array p_array = str;  // ptr_array p_array;等价于 char (*p_array)[30];
        ptr_func p_func = max;  // ptr_func p_func;等价于 int (*p_func)(int, int); 
        cout << "max:" << (*p_func)(10, 20) << endl;
        for(int i = 0; i < 3; i++)
                cout << "str[" << i << "] = " << *(p_array+i) << endl;
            return 0;
        }
    
  • 需要强调的是,typedef是赋予现有类型一个新的名字,而不是创建新的类型。为了“见名知意”,请尽量使用含义明确的标识符,并且尽量大写

2.typedef和#define的区别

  • typedef在表现上有时候类似#define,但它和宏替换之间存在一个关键性的区别。正确思考这个问题的方法就是把typedef看成一种彻底的“封装”类型,声明之后不能再往里面增加别的东西。
    • 可以使用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。如下所示:
          #define INT int
          unsigned INT n;  // 没问题
      
          typedef int INT;
          unsigned INT n;  // 错误!不能在INT前加unsigned
      
    • 在连续定义几个变量的时候,typedef能够保证定义的所有变量均为同一类型,而#define则无法保证.例如:
          #define PTR_INT int *
          PTR_INT p1, p2;  
      
    • 经过宏替换后,第二行变为:
          int *p1, p2;  // p1 p2是不同的数据类型,p1是指向int类型的指针,p2是int类型
      
    • 相反,使用typedef则不会出现问题:
          typedef int * PTR_INT;
          PTR_INT p1, p2;  // p1、p2 类型相同,它们都是指向 int 类型的指针。