标签:
typedef
声明,简称typedef
,为现有类型创建一个新的名字。比如人们常常使用 typedef
来编写更美观和可读的代码。所谓美观,意指typedef
能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。
定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。
char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,和一个字符变量;
//以下则可行:
typedef char* PCHAR;
PCHAR pa, pb;
typedef
并不创建新的类型。它仅仅为现有类型添加一个同义字。
以前的代码中,声明struct
新对象时,必须要带上struct
,即形式为: struct
结构名
对象名,如:
struct tagPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;
而在C++
中,则可以直接写:结构名对象名,即:tagPOINT1
p1;
typedef struct tagPOINT
{
int x;
int y;
}POINT;
POINT p1;
// 这样就比原来的方式少写了一个struct
,比较省事,尤其在大量使用的时候,或许,在C++
中,typedef
的这种用途不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的。
比如定义一个叫 REAL
的浮点类型,在目标平台一上,让它表示最高精度的类型为:
typedef long double REAL;
在不支持 long double
的平台上,改为:
typedef double REAL;
在连 double
都不支持的平台上,改为:
typedef float REAL;
也就是说,当跨平台时,只要改下typedef
本身就行,不用对其他源码做任何修改。
标准库就广泛使用了这个技巧,比如size_t
。另外,因为typedef
是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。
typedef
还可以掩饰符合类型,如指针和数组。
typedef int MyIntArray[100]; //MyIntArray表示一个包含100个整形的数组
那么程序中的
MyIntArray ia; //ia是个包含100个整形的数组
就相当于
int ia[100];
应用于指针:
typedef char * pstr; //pstr 是一个指向char的指针哈
int mystrcmp(pstr, pstr); //两个参数可是两个指针
上面讨论的 typedef
行为有点像#define
宏,用其实际类型替代同义字。不同点是 typedef
在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换。
typedef void (*FUNCADDR)(int)
此处FUNCADDR
是指向这样一个函数的指针,该函数的返回值为void
类型,函数有一个int
型的参数。再例如:
void print (int x)
{
printf ("%d\n", x);
}
int main (int argc, char *argv[])
{
FUNCADDR pFunc;
pFunc = print; // 将指针指向print函数
(*pFunc)(25); // 调用函数print
return 0;
}
来,一起看一个更复杂的:
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
不是一种特权,而是一种必需。
基本解释
typedef
为C
语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int
,char
等)和自定义的数据类型(struct
等)。
在编程中使用typedef
目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
至于typedef
有什么微妙之处,请你接着看下面对几个问题的具体阐述。
当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C
语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:
typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
答案与分析:
1. typedef
的最简单使用
typedef long byte_4;
给已知数据类型long
起个新名字,叫byte_4
。
typedef
与结构结合使用
typedef struct tagMyStruct
{
int iNum;
long lLength;
} MyStruct;
这语句实际上完成两个操作:
1) 定义一个新的结构类型
struct tagMyStruct
{
int iNum;
long lLength;
};
分析:tagMyStruct
称为tag
,即“标签”,实际上是一个临时名字,struct
关键字和tagMyStruct
一起,构成了这个结构类型,不论是否有typedef
,这个结构都存在。
我们可以用struct tagMyStruct varName
来定义变量,但要注意,使用tagMyStruct
varName
来定义变量是不对的,因为struct
和tagMyStruct
合在一起才能表示一个结构类型。
2) typedef
为这个新的结构起了一个名字,叫MyStruct
。
typedef struct tagMyStruct MyStruct;
因此,MyStruct
实际上相当于struct
tagMyStruct
,我们可以使用MyStruct varName
来定义变量。
答案与分析:
C
语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef
的应用。
根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext
域的声明,类型是pNode
,要知道pNode
表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode
。
解决这个问题的方法有多种:
1)第一种
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
2)第二种
typedef struct tagNode *pNode;
struct tagNode
{
char *pItem;
pNode pNext;
};
注意:在这个例子中,你用typedef
给一个还未完全声明的类型起新名字。C
语言编译器支持这种做法。
3)、规范做法:
struct tagNode
{
char *pItem;
struct tagNode *pNext;
};
typedef struct tagNode *pNode;
标签:
原文地址:http://blog.csdn.net/yapian8/article/details/42776141