最近刚刚跳槽,进入一个新的公司,处于学习期间,工作不是太忙。看到一些前人们开发的代码,忽然发现自己对typedef这个东东还没有系统的了解过。于是乎上网”狗狗”了一下,做了点总结,现整理如下:
Typedef的作用:为现有的类型创建一个新的名字。主要优点有两个:
1) 使代码更加美观,可读性更强,隐藏复杂和难以理解的语法;
2) 有助于创建平台无关的类型,增强可移植性和可维护性。
下面,对这些优点举例说明一下,若有错误之处,希望高人之处;若有遗漏之处,也热烈欢迎各位补充
1,使用 typedefs 为现有类型创建同义字。
typedef 使用最多的地方是创建新的类型名称,这些名称往往被定义的易于记忆,并且能够体现程序员的意图,例如:
typedef int size;
这里定义了int类型的新的名称:size。需要注意的是,typedef并没有创建新类型,它创建的是现有类型的新名称。你可以在任何需要 int 的上下文中使用 size:
void calculate(size * psz);
size Array[4];
typedef还可以掩饰复合类型,如指针和数组。比如当要用到相同类型和大小的数组时,可以使用typedef。例如,假如我们要定义2个数组,各包含10个int:
int arrayOne[10];
int arrayTwo[10];
用typedef定义如下所示:
typedef int Array[10]; // Array是一个新的类型名称,表示10个int元素的数组。
Array arrayOne, arrayTwo;
getline(text);
同样,可以象下面这样对待指针:
typedef char * pstr;
int mystrcmp(pstr, pstr);
注意这里 typedef会给我们带来一个陷阱。标准函数 strcmp()有两个‘const char *'类型的参数。因此,它可能会误导人们象下面这样声明 mystrcmp():
int mystrcmp(const pstr, const pstr);
这是错误的,因为typedef不是#define,它不是简单的字符串替换。Pstr被typedef为一个指向char类型的指针,‘const pstr'被解释为一个指向 char 的常量指针,既’char * const’,而不是‘const char *'(指向常量 char 的指针)。要解决这个问题,可以如下定义指针:
typedef const char * cpstr;
int mystrcmp(cpstr, cpstr); // 现在是正确的
2,代码简化
typedef 在编译时被解释,由编译器来进行文本替换(#define是由于处理器来稿定的)。例如:
typedef int (*PF) (const char *, const char *);
这个声明引入了 PF 类型作为函数指针的同义字,该函数有两个 const char * 类型的参数以及一个 int 类型的返回值。如果要使用下列形式的函数声明,那么上述这个 typedef 是不可或缺的:
PF Register(PF pf);
Register() 的参数是一个 PF 类型的回调函数,返回某个函数的地址,其署名与先前注册的名字相同。做一次深呼吸。下面我展示一下如果不用 typedef,我们是如何实现这个声明的:
int( *Register ( int ( *pf ) ( const char*, const char* ) ) ) ( const char *, const char * );
很少有程序员理解它是什么意思,更不用说这种费解的代码所带来的出错风险了。显然,这里使用 typedef 不是一种特权,而是一种必需。持怀疑态度的人可能会问:"OK,有人还会写这样的代码吗?",快速浏览一下揭示 signal()函数的头文件 ,一个有同样接口的函数。
3,typedef 和存储类关键字(storage class specifier)
typedef 就像 auto,extern,mutable,static,和 register 一样,是一个存储类关键字。但是请注意:typedef事实上不会影响对象的存储特性,只是在语句构成上,typedef的声明看起来象 static,extern 等类型的变量声明。下面将带到第二个陷阱:
typedef register int FAST_COUNTER; // 错误
编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,在 typedef 声明中不能用 register(或任何其它存储类关键字)。
4,便于跨平台开发
typedef 的重要用途之一就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型:
typedef long double REAL;
在不支持 long double 的机器上,应该像下面这样定义:
typedef double REAL;
如果在连 double 都不支持的机器上,:
typedef float REAL;
这样便可以在每一种平台上编译这个使用 REAL 类型的应用程序,不需要对客户代码进行任何修改。唯一要改的是 typedef 本身,而在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的条件编译(#if, #else, #elif, #endif, #ifdef, #ifndef等等)来自动实现。