周立功

深入理解typedef

0
阅读(2965)

typedef作为C语言的关键字,它是用来建立新的数据类型名,这里所指的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。

在编程中使用typedef的好处,除了为变量取一个简单易记且意义明确的新名称之外,还可以简化一些比较复杂的类型声明。比如:

         typedef int INT32;

    将INT32定义为与int具有相同意义的名字,这样类型INT32就可用于类型声明与类型转换了,它和类型int完全相同。

既然已经有了int这个名称,为什么还要再取一个名称呢?主要是为了提高程序的可移植性。比如,某种微处理器的int为16位,long为32位。如果要将该程序从某种微处理器移植到个人计算机,由于一般编译器的int为32位,long为64位,而只有short才是16位的,因此必须将程序中的int全部替换为short,long全部替换为int,如此这样修改势必工作量巨大且容易出错。如果将它取一个新的名称,然后在程序中全部用新取的名称,那么要移植的工作仅仅只是修改定义这些新名称即可。也就是说,只需要将以前的:

         typedef int INT16;

         typedef long INT32;

替换成:

     typedef short INT16;

         typedef int INT32;

由此可见,typedef声明并没有创建一个新类型,而是为某个已经存在的类型增加一个新的名字而已。用这种方式声明的变量与通过声明方式声明的变量具有完全相同的属性。

至于typedef如何简化复杂的类型声明,将在后续的章节中详细阐述。

综上所述,如果在变量定义的前面加上typedef,即可定义该变量的类型。比如:

         int size;

    这里定义了一个整型变量size,当加上typedef后:

         typedef int size;

那么,size就成为了上面的size变量的类型,即int类型。既然size是一个类型,当然可以用它来定义另外一个变量。即:

         size a;

 

    类似于变量的类型定义,也可以用typedef声明新的类型,比如:

         char              *ptr_to_char;        // 声明ptr_to_char为一个指向字符的指针

         typedef  char     ptr_to_char;         // 声明ptr_to_char为指向char的指针类型

         ptr_to_char       pch;                 // 声明pch是一个指向字符的指针

    对于初学者来说,也许会产生一个这样的疑问,为什么不使用#define创建新的类型名?比如:

         #define  ptr_to_char  char*

         ptr_to_char           pch1, pch2;

    虽然#define语句类似于typedef,但在编译时却有不同的解释。对于#define来说,预处理器在编译前先做替换处理;而对于typedef来说,它是由编译器来解释的。由此可见,用#define除了正确地声明了pch1之外,却无法将pch2预处理为指针,从而可以看出typedef的文本替换功能比预处理器的能力要强得多。

 

    在指针函数中,有这样一类函数,它们也返回指针,但是这个指针不是指向int、char之类的基本类型,而是指向函数。对于初学者,别说写出这样的函数声明,就是看到这样的写法也是一头雾水。比如,下面的语句:

         int (*ff(int))(int *, int);

我们用上面介绍的方法分析一下,ff首先与后面的“()”结合,即:

         int (*(ff(int)))(int *, int);                   // 用括号将ff(int)再括起来

也就意味着,ff是一个函数。

    接着与前面的“*”结合,说明ff函数的返回值是一个指针。然后再与后面的“()”结合,也就是说,该指针指向的是一个函数。

这种写法确实让人非常难懂,以至于一些初学者产生误解,认为写出别人看不懂的代码才能显示自己水平高。而事实上恰好相反,能否写出通俗易懂的代码是衡量程序员是否优秀的标准。一般来说,用typedef关键字会使该声明更简单易懂。在前面我们已经见过:

         int (*PF)(int *, int);

也就是说,PF是一个函数指针“变量”。当使用typedef声明后,则PF就成为了一个函数指针“类型”,即:

         typedef int (*PF)(int *, int);

这样就定义了返回值的类型。然后,再用PF作为返回值来声明函数:

         PF ff(int);

    返回函数指针会用在什么地方呢?且听下文分解。