C语言中Typedef的使用方法3
李 钢,黄湘萍,许 焰
(长沙大学机电工程系,湖南长沙 410003)
摘 要:在C语言中,除可以直接使用标准类型名(如int、char、float、double等)和自定义的结构体、共用体、指针、枚举类型外,还可以用Typedef定义新的类型名来代替已有的类型名1如果能熟练使用Ty2 pedef,将有利于建立与平台无关的数据类型,甚至能隐藏一些复杂和难以理解的语法,避免一些常见的错误,从而使C程序代码更灵活1
关键词:变量;数据类型;结构体;指针
中图分类号:TP312  文献标识码:A  文章编号:100824681(2007)0920070204define的基本用法
  typedef声明,简称typedef,为现有的数据类型创建一个新的名字1用typedef定义新的类型名后,对于结构体、共用体或枚举类型,使用它们定义或说明变量时,不必再冠以类型类别关键字,一般常使用typedef
来编写更为美观和可读性较强的代码.所谓美观,即指typedef能隐藏较笨拙的语法构造以及平台相关的数据类型,从而增强程序的可移植性、以及将来的可维护性1本文将揭示typedef 强大功能1
1 C语言中typedef基本用法[1,2,3]
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字1这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(st ruct 等)1
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明1
1.1 typedef的最简单使用
typedef int integer;
给已知数据类型int定义为integer,这样,以下两行代码是等价的:
int a,b;
integ a,b;
1.2 typedef与结构结合使用
typedef st ruct tagMyStruct
 {int iNum;
  long lLengt h;
 }MySt ruct;
这组语句实际上完成两个操作:1.2.1 定义一个新的结构类型
st ruct tagMySt ruct
 {int iNum;
 long lLengt h;
};
1.2.2 typedef为这个新的结构起了一个名字,叫MySt ruct
typedef st ruct tagMySt ruct MyStruct;
分析:tagMySt ruct称为“tag”,即“标签”,实际上是一个临时名字,关键字st ruct和tagMySt ruct 一起,构成了这个结构类型,不论是否有typedef,这个结构都存在1
可以用st ruct tagMySt ruct varName来定义变量,但要注意,使用tagMySt ruct varName来定义变量是不对的,因为st ruct和tagMySt ruct合在一起才能表示一个结构类型1
因此,MyStruct实际上相当于st ruct tagMy2 St ruct,可以使用MySt ruct varName来定义变量1
1.3 typedef可定义指针、数组、枚举等类型
typedef还可以定义指针、数组、枚举类型等数据类型,如:
(1)typedef int num[100];//声明num为整型数组类型
num n;//定义n为整型数组变量
(2)typedef char3st ring;//声明st ring为字符指针类型
3收稿日期:2007205222;修回日期:2007206219
作者简介:李 钢(1965-)男,湖南长沙人,长沙大学机电工程系实验师1研究方向:计算机网络与计算机管理.
st ring p,s[10];//定义p为字符指针变量,s为指针数组
(3)typedef int(3pointer)()//声明pointer为指向函数的指针类型,该函数返回整型值
pointer p1,p2;//定义p1、p2为pointer类型的指针变量
(4)typedef enum{sun,mon,t ues,wed,t hur,
f ri sat}days;//声明days为枚举类型
days today;//定义today为days类型的变量
2 typedef和结构的问题
至于typedef到底有什么微妙之处,可以从下面的几个问题得到答案1
当用下面的代码定义一个结构时,编译器会报类型错误1
typedef st ruct tagNode
 {char3p Item;
  pNode pNext;
 }3p Node;
C语言允许在结构中包含指向它自己的指针,这可以从建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用1
根据前面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字不存在,也就是说这个时候编译器根本不能识别pNode1解决这个问题的方法下列3种:
(1)常用方法有两种:
①typedef struct tagNode
{char3p Item;
 st ruct tagNode3pNext;
}3pNode;
②typedef struct tagNode3pNode;
st ruct tagNode
{char3p Item;
 p Node p Next;
};
注意:这个例子中,typedef给一个还未完全声明的类型起新名字1C语言编译器支持这种做法1
(2)规范做法:
st ruct tagNode
{char3p Item;
 st ruct tagNode3pNext;
};
typedef st ruct tagNode3pNode;
3 typedef和#def ine的问题[1,2]
有下面两种定义p St r数据类型的方法,两者有什么不同?哪一种更好一点?
typedef char3p St r;
#define p Str char3;
通常,typedef要比#define要好,特别是在有指针的场合1
typedef char3p St r1;
#define p Str2char3;
p St r1s1,s2;
p St r2s3,s4;
在上述的变量定义中,s1、s2、s3都被定义为char3,而s4则定义成了char,不是所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字1
#define用法例子:
#define f(x)x3x
main()
 {int a=6,b=2,c;
  c=f(a)/f(b);
  p rintf("%d\n",c);
 }
程序的输出结果是:361
因此,在C语言编程规范中,使用#define定义时,如果定义中包含表达式,必须使用括号,则上述定义应该如下定义才对:
#define f(x)(x3x)
如果使用typedef就没有这样的问题出现1
typedef和#define的另一例
下面的代码在编译器中也会出问题:
typedef char3p St r;
char st ring[4]="abc";
co nst char3p1=st ring;
co nst p St r p2=st ring;
p1++;
p2++;
是p2++出错了1这个问题再一次说明:ty2 pedef和#define不同,它不是简单的文本替换1上述代码中const
p St r p2并不等于const char3 p21const p St r p2和const long x本质上没有区别,都是对变量进行只读限制,只是此处的变量p2数据
17
 总第79期          李 钢,黄湘萍,许 焰 C语言中Typedef的使用方法
类型是自定义的而不是系统固有类型1因此,co nst p St r p2的含义是:限定数据类型为char3的变量p2为只读,因此p2++错误1
#define与typedef的区别:
(1)#define宏定义有一个特别的长处:可以使用#if def,#if ndef等来进行逻辑判断,还可以使用#undef来取消定义1
(2)typedef也有一个特别的长处:它符合范围规则,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种特性1
这里有两点值得注意:
(1)用typedef只是给已有类型增加1个别名,并不能创造1个新的类型1
(2)typedef与#define有相似之处,但二者是不同的:前者是由编译器在编译时处理的;后者是由编译预处理器在编译预处理时处理的,而且只能作简单的字符串替换1
4 typedef复杂的变量声明
在编程实践中,尤其是看别人代码的时候,常常会遇到比较复杂的变量声明,使用typedef作简化自有其价值,比如:
下面是三个变量的声明,如想使用typdef分别给它们定义一个别名,该如何做?
(1)int3(3a[5])(int,char3);
(2)void(3b[10])(void(3)());
(3)doube(3)()(3pa)[9];
对复杂变量建立一个类型别名的方法很简单,只要在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了1
(1)int3(3a[5])(int,char3);//p Fun是新建的一个类型别名
typedef int3(3p Fun)(int,char3);
//使用定义的新类型来声明对象,等价于int3 (3a[5])(int,char3);
p Fun a[5];
(2)void(3b[10])(void(3)());//首先为void(3)声明一个新类型
typedef void(3p FunParam)();//整体声明一个新类型
typedef void(3p Fun)(p FunParam);
//使用定义的新类型来声明对象,等价于void (3b[10])(void(3)());
p Fun b[10];
(3)doube(3)()(3pa)[9];
//首先为doube(3)()声明一个新类型
typedef double(3p Fun)();
/
/整体声明一个新类型
typedef p Fun(3p FunParam)[9];
//使用定义的新类型来声明对象,等价于doube(3)()(3pa)[9];
p FunParam pa;
5 创建平台无关的数据类型,隐藏笨拙且难以理解的语法
  使用typedef s为现有类型创建同义字1定义易于记忆的类型名
typedef使用最多的地方是创建易于记忆的类型名,用它来归档程序员的意图1类型出现在所声明的变量名字中,位于“typedef”关键字右边1例如:
typedef int size;
此声明定义了一个int的同义字,名字为size1注意typedef并不创建新的类型1它仅仅为现有类型添加一个同义字1可以在任何需要int的上下文中使用size:
void measure(size3p sz);
size array[4];
size lengt h();
st d::vector vs;
typedef还可以掩饰符合类型,如指针和数组1不用象下面这样重复定义有81个字符元素的数组: char line[81];
char text[81];
定义一个typedef,每当要用到相同类型和大小的数组时,可以这样:
typedef char Line[81];
Line text,secondline;
getline(text);
同样,也可以象下面这样隐藏指针语法:
typedef char3p st r;
int myst rcmp(p str,p st r);
这里将带来个typedef的一个误区1标准函数strcmp()有两个‘const char3’类型的参数1因此,有可能会误导用象下面这种方式声明mystrcmp ():
int myst rcmp(const p st r,const p st r);
这种方式是错误的,按照顺序,‘const p st r’被解
27长沙大学学报                 2007年9月 
释为‘char3const’(一个指向char的常量指针),而不是‘const char3’(指向常量char的指针)1正确解决这个问题的方法是:
typedef const char3cp st r;
int myst rcmp(cp st r,cp str);
只要为指针声明typedef,那么都要在最终的typedef名称中加一个const,以使得该指针本身是常量,而不是对象1
6 代码简化
上面讨论的typedef行为有点像#define宏,用其实际类型替代同义字1不同点是typedef在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换1例如:
typedef int(3PF)(const char3,const char 3);
这个声明引入了PF类型作为函数指针的同义字,该函数有两个const char3类型的参数以及一个int类型的返回值1如果要使用下列形式的函数声明,那么上述这个typedef是不可或缺的: PF Register(PF pf);
Register()的参数是一个PF类型的回调函数,返回某个函数的地址,其署名与先前注册的名字相同1如果不用typedef,将如何实现这个声明的: int(3Register(int(3pf)(const char3, const char3)))
(const char3,const char3);
很难理解这是什么意思,更不用说这种费解的代码会带来什么风险1在这里使用typedef是一种必需17 促进跨平台开发
typedef还有另一个重要的用途,那就是定义与机器无关的类型1
如可以定义一个叫REAL的浮点类型,在目标机器上它可以获得最高的精度:
typedef long double REAL;
在不支持long double的机器上,该typedef看起来会是下面这样:
typedef double REAL;
并且,在连double都不支持的机器上,该ty2 pedef看起来会是这样:
typedef float REAL;
不用对源代码做任何修改便可以在每一种平台上编译这个使用REAL类型的应用程序1唯一需要改的是typedef函数本身1在大多数情况下,这个微小的变动完全都可以通过编译来自动实现1
8 小结
Typedef声明符的使用使得C语言程序在可移植性、简洁性方面有较大提高,极详细分析了常见的Ⅷ种使用方法及其使用后在程序改进方面的变化,由此可以看出typedef声明符的强大功能,事实上typedef应该还有更多的应用有待进一步挖掘,灵活运用typedef会对C语言编写带来更多的好处1
参考文献:
[1]杨路明.C语言程序设计教程[M].北京:北京邮电大学出版社,
2005.
[2]谭浩强.C程序设计[M].北京:清华大学出版社,1991.
[3]潘金贵,沈默君,谢俊元,等.TORBO语言及其程序设计[M].南
京:南京大学出版社,1988.
(作者本人校对)
37
 总第79期          李 钢,黄湘萍,许 焰 C语言中Typedef的使用方法

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。