彼の一存

The place where the past meets the present to contemplate the future

typedef 的那些事儿

typedef 简述

typedef 是在计算机编程语言中用来为复杂的声明定义简单的别名,与宏定义有些差异。 它本身是一种存储类的关键字,与 auto、extern、mutable、static、register 等关键字不能出现在同一个表达式中。

关于这个问题,举个栗子:

typedef register int FAST_COUNTER; // 错误

编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,在 typedef 声明中不能用 register(或任何其它存储类关键字)。

typedef vs #define

#define 的优势

  1. #define 宏定义有一个特别的长处:可以使用 #ifdef, #ifndef 等来进行逻辑判断,还可以使用 #undef 来取消定义。
  2. #define 宏是预处理器处理的。

typedef 的优势

  1. typedef 也有一个特别的长处:它符合范围规则,使用 typedef 定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性。
  2. typedef 是编译器处理的。

typedef 实现复杂的变量声明

提问

在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,此时可以使用 typedef 做化简。下面是三个变量的声明,如果要使用 typdef 分别给它们定义一个别名,该如何实现?

/* 1. */ int *(*a[5])(int, char*);
/* 2. */ void (*b[10]) (void (*)());
/* 3. */ double(*)() (*pa)[9];

答案与分析:

对复杂变量建立一个类型别名的方法很简单,你只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字 typedef 加在该语句的开头就行了。

/* 1. */
int *(*a[5])(int, char*);
//pFun 是我们建的一个类型别名
typedef int *(*pFun)(int, char*);
//使用定义的新类型来声明对象,等价于 int* (*a[5])(int, char*);
pFun a[5];

/* 2. */
void (*b[10]) (void (*)());
//首先为上面表达式蓝色部分声明一个新类型
typedef void (*pFunParam)();
//整体声明一个新类型
typedef void (*pFun)(pFunParam);
//使用定义的新类型来声明对象,等价于 void (*b[10]) (void (*)());
pFun b[10];

/* 3. */
double(*)() (*pa)[9];
//首先为上面表达式蓝色部分声明一个新类型
typedef double(*pFun)();
//整体声明一个新类型
typedef pFun (*pFunParam)[9];
//使用定义的新类型来声明对象,等价于 double(*)()(*pa)[9];
pFunParam pa;
//pa 是一个指针,指针指向一个数组,这个数组有 9 个元素,每一个元素都是“doube(*)()”--也即一个指针,指向一个函数,函数参数为空,返回值是“double”。

typedef 在跨平台时的优势

typedef 有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型,在目标机器上它可以获得最高的精度:

typedef long double REAL;

在不支持 long double 的机器上,该 typedef 看起来会是下面这样:

typedef double REAL;

并且,在连 double 都不支持的机器上,该 typedef 看起来会是这样:

typedef float REAL

你不用对源代码做任何修改,便可以在每一种平台上编译这个使用 REAL 类型的应用程序。唯一要改的是 typedef 本身。在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的 条件编译1来自动实现。

typedef 的一些注意事项

注意事项一

typedef char* pstr;   
int mystrcmp(const pstr p1,const pstr p3);

用 GNU 的 gcc 和 g++ 编译器,是会出现警告的,按照顺序, const pstr 被解释为 char* const (一个指向 char 的指针常量),而事实上, const char*char* const 表达的并非同一意思(详见 C++ Primer 第四版 P112)。

  • char * const cp : 定义一个指向字符的指针常数,即 const 指针,常指针。
  • const char* p : 定义一个指向字符常数的指针,即常量指针。
  • char const* p : 等同于 const char* p。

为了得到正确的类型,应当如下声明:

typedef const char* pstr;

注意事项二

typedef 遵循着和 #define 不一样的定义规则。规则比较奇怪,这里也是举个栗子说明:

定义有 81 个字符元素的数组,无 typedef 版本:

char line[81];
char text[81];

定义有 81 个字符元素的数组,有 typedef 版本:

typedef char Line[81];
Line text,line;

脚注:

1

#if、#else、#elif、#endif 等等,#define 的情况会使用 #ifdef 和 #ifndef(也是用 #endif 结尾)。

Comments

使用Disqus评论
comments powered by Disqus