一、问题
typedef 关键字的功能就是给⼀个已经存在的数据类型起⼀个在本程序中能够体现实际作⽤的名字。#define 宏定义是为⼀个字符串起⼀个别名,在程序中应⽤到该字符串时, ⽤这个别名来替代。那么 typedef 与 #define 的相似之处是什么,不同之处又是什么呢?
二、解答
1. #define 与 typedef 的相似之处
宏定义和类型定义有很多相似之处,通常都可以理解为为⼀个字符起别名,在程序中⽤⼀个新的字符代替原有的字符。例如:
#define STRINT chartypedef char STRING;
这两句代码都是⽤ STRING 代替原有的字符 char。⽽ STRING str;的含义是定义了⼀个 char 型的变量 str。 在此例中,宏定义和类型定义起到的作⽤是相同的,但实质上是有区别的。
2. 两者的区别
(1)在上述为 char 起别名的两种⽅法中,实质含义是不同的。
例如,#define 是在预编译时⽤ STRING 这个字符串代替 char 这个字符串;⽽ typedef 是为 char 字符串类型定义了⼀个别名,并不是简单的字符串替换。STRING 这个字符串与 char 的功能相同,代表了 ⼀个字符串类型的数据类型。
请看下⾯的例⼦,观察两者的区别。
#define INTP int*typedef int* INTP;
其中“ INTP a,b; 〞在宏定义的定义下,可以理解成 “ int *a,b; ”,表示声明了⼀个整型指针变量a 和⼀个整型变量 b ;若在类型定义的定义下,可以将其理解成 “ int *a;int *b; ”,表示声明了两个整型变量指针 a 和 b 。
(2)宏定义和类型定义还有⼀个很⼤的区别,然⽽却往往被⼈忽略。
那就是宏定义的句尾没有分号作为结束语句的标志;若有,就会被当做字符串替换进程序中。由此可以更明显地看出,宏定义通常被⽤作定义常量,以及⽤来实现“ 表⾯似和善,背后⼀长串” 的宏,⽽且其本⾝并不在编译过程中进⾏,⽽是在预处理过程中就已经完成了。因此,很难发现潜在的错误及代码维护问题。
例如,代码“ #define PI 3.1415926; ”只在程序源代码中应⽤到 PI 时才会出现编译错误,错误就在于⽤ PI 这个字符代替了“ 3.1415926; ”这个字符串,⽐正常的数字多了个分号。
三、总结
#define 原本在 C 语⾔中是为了定义常量,然⽽随着 C++ 中的 const、 enum 和 inline 的出现,使它渐渐地变成了起别名的⼯具。但是,在定义别名这个功能上,最好还是习惯应⽤ typedef。
为了尽可能地兼容,⼀般都遵循#define 定义 “ 可读 ” 的常量(常量表达式), ⽽ typedef 则常⽤来定义关键字或元长的数据类型的别名。