14.12 typedef简介

typedef工具是一种高级数据特性,它使您能够为某一类型创建您自己的名字。在这个方面,它和#define相似,但是它们具有3个不同之处:

● 与#define不同,typedef给出的符号名称仅限于对类型,而不是对值。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

● typedef的解释由编译器,而不是预处理器执行。

● 虽然它的范围有限,但在其受限范围内,typedef比#define更灵活。

我们来看看typedef是怎样工作的。假设要对1字节的数值使用术语BYTE,您只须像定义一个char变量那样定义BYTE,然后在这个定义前面加上关键字typedef,如:

阅读 ‧ 电子书库

随后您就可以使用BYTE来定义变量了:

阅读 ‧ 电子书库

该定义的作用域取决于typedef语句所在的位置。如果定义是在一个函数内部,它的作用域就是局部的,限定在那个函数里。如果定义是在函数外部,它将具有全局作用域。

通常,这些定义使用大写字母,以提醒用户这个类型名称实际上是一个符号缩写。不过,您也可以使用小写字母:

阅读 ‧ 电子书库

管理变量名的同样规则也用来管理typedef使用的名字。

为一个已经存在的类型创建一个名字可能看起来没有什么必要,然而这可能会是有用的。在前面的例子中,使用BYTE来代替unsigned char有助于说明您打算用BYTE变量来表示数值而非字符编码。使用typedef也有助于增加可移植性。例如,我们已经提到过表示sizeof运算符返回类型的size_t类型,以及表示函数time()的返回值类型的time_t类型。C标准规定sizeof和time()应返回整数类型,但它留给具体的实现来决定到底是哪种整数类型。不进行指定的原因是ANSI C委员会觉得没有一个对所有计算机平台来说都是最好的选择。因此他们提出一个新类型名称,如time_t,让C实现使用typedef来把这个名称设定为某种特定的数据类型。这样,他们可以提供下列通用原型:

阅读 ‧ 电子书库

在一个系统上,time_t可能是unsigned int类型;在另一个系统上,它可能是unsigned long类型。只要包含了time.h头文件,程序就可以访问适当的定义,您也可以在代码中声明time_t变量。

使用#define可以实现typedef的一部分功能。例如:

阅读 ‧ 电子书库

这使预处理器用unsigned char来代替BYTE。但也有#define实现不了的功能,如下例所示:

阅读 ‧ 电子书库

如果没有关键字typedef,该例将STRING识别为一个char指针。有了这个关键字,使STRING成为char指针的标识符。因此:

阅读 ‧ 电子书库

意思是:

阅读 ‧ 电子书库

但是,假设这样做:

阅读 ‧ 电子书库

那么:

阅读 ‧ 电子书库

将会被翻译成下面的形式:

阅读 ‧ 电子书库

在这种情况下,只有name是一个指针。

也可以对结构使用typedef:

阅读 ‧ 电子书库

这样您就可以用类型COMPLEX代替struct complex来表示复数。使用typedef的原因之一是为经常出现的类型创建一个方便的、可识别的名称。例如,在前面的例子中,许多人都愿意使用STRING或与其等价的标记。

使用typedef来命名一个结构类型时,可以省去结构的标记:

阅读 ‧ 电子书库

假设像下面这样使用typedef定义的类型名:

阅读 ‧ 电子书库

这被翻译成:

阅读 ‧ 电子书库

如果两个结构的声明都不使用标记,但是使用同样的成员(成员名和类型都匹配),那么C认为这两个结构具有同样的类型,因此将r1赋给r2是一个正确的操作。

使用typedef的另一个原因是typedef的名称经常被用于复杂的类型。例如:

阅读 ‧ 电子书库

这把FRPTC声明为一个函数类型,该类型的函数返回一个指向含有5个元素的char数组的指针(请参见下面将要讨论的一些奇特的声明)。

当使用typedef时,要记住它并不创建新的类型;它只是创建了便于使用的标签。这意味着,例如,我们创建的STRING类型的变量可以作为参数传递给需要char指针类型参数的函数。

通过结构、联合和typedef, C提供了有效和方便地处理数据的工具。