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 类型的指针。
- 可以使用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。如下所示: