标签:
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); // 调用函数printreturn 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