typedef全面分析

typedef在计算机编程语言中用来为复杂的声明定义简单的别名,与宏定义有些差异。它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。typedef能隐藏笨拙的语法构造以及平台相关的数据类型。typedef有点像#define宏,用其实际类型替代同义词,不同的是typedef在编译时被解释,因此让编译器来应付超越预处理能力的文本替换。

1.定义一种类型的别名,例如:(1)给变量一个容易记忆意义明确的名字:typedef unsignedintsize_t; size_t len[4];

(2)typedef 还可以掩饰复合类型,如指针和数组 typedef chat SIZE[81]; 此时的SIZE类型代表具有81个元素的字符数组,使用方法如下:SIZE text;

typedef char* PSTR; PSTR p1,p2;

陷阱一:int mystrcmp(const PSTR p1, const PSTR p2);用GNU的gcc和g++编译器则会编译告警。因为他将被解释为char*const,原因是const给予整个指针本身以常量,即const指针,常指针。


p2++错误,此例子告诉我们typedef和#define不同,他不是简单的文本替换。此处和上处解释相同均为char* const  p2 。const pStr p2和const long x本质上没有区别,都是对变量进行只读限制,只不过此处变量p2的数据类型是我们自己定义的而不是系统固有类型而已。因此,const pStr p2的含义是:限定数据类型为char *的变量p2为只读,因此p2++错误。

陷阱二:用下面的代码定义结构,C编译器报错


原因是类型未定义完就使用。解决办法:

typedef struct tagNode

{

char *pItem;

struct tagNode * pNext

}pNode;

且在旧C语言中(非C++)不支持 不带struct声明新对象。


(3) typedef和define的另一个区别:

typedef char* pstr1;

#define pstr2 char*;

pstr1 s1,s2;

pstr2 s3,s4;-------此处将会出现与预期不符合,s4为char型,若想与预期相符合,则应该改为:pstr2 s3, *s4;

(4)#define与typedef引申谈

1) #define 宏定义有一个特别的长处:可以使用 #ifdef ,#ifndef等来进行逻辑判断,还可以使用#undef来取消定义。
2) typedef也有一个特别的长处:它符合范围规则,使用typedef定义的 变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而 宏定义则没有这种特性。
(5)typedef用于复杂的变量声明:在传统的变量声明表达式里用类型名替代变量名,然后把关键字typedef加在该语句的开头就行了。
①:int*(*a[5])(int, char*);----->别名pFun---->typedef int*(*pFun)(int,char*);使用定义的新类型来声明对象,等价于 int*(*a[5])(int, char*);=====pFun a[5];
②:void(*b[10])(void(*)());--->先替换右边的括号typedef void(*pFunParam)();再整体将变量名b声明为一个新的类型typedef void(*pFun)(pFunParam);原始的数据等价于 pFun b[10];
③: doube(*)() (*pa)[9];变量名为pa,---->先替换pa左边的部分,typedef double(*pFun)();再将整体替换typedef pFun(*pFunParam)[9];原始的数据等价于pFunParam pa;
④:typedef struct 
{
int a;
}MY_TYPE;-------------------------未命名的结构体的别名。
陷阱三:typedef和auto,extern,mutable,static,和 register 一样,是一个存储类关键字。typedef register int FAST_COUNTER;上式编译不过,因为typedef占据了存储类的关键字的位置,则不能再用register 。
(6)平台开发:可以定义与机器无关的类型。例如:typedef long double REAL;无需对源代码修改,便可以在每一种平台上使用REAL类型的应用程序。只需改动typedef本身。这个微小的改变甚至可以通过条件编译来实现。size_t即是类似的类型。
(7)引用网络: 上面讨论的 typedef 行为有点像 #define 宏,用其实际类型替代同义字。不同点是 typedef 在编译时被解释,因此让 编译器 来应付超越 预处理器 能力的 文本替换 。例如:
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 不是一种特权,而是一种必需。持怀疑态度的人可能会问:"OK,有人还会写这样的代码吗?",快速浏览一下揭示 signal()函数的头文件 ,一个有同样接口的函数。
分析方法:例:typedef int (*pFUN)(int, int );
函数定义别名,上例是定义pFUN一个函数指针,参数类型为两个整数,并且返回值是int类型,分析此形式可采用下列方法:去掉typedef和别名,剩下的就是原变量的类型:int(*)(int,int);
使用方法:
pFUN pFun;
int g1Fun(int a, int b){return ;}
void main()
{
pFun= g1Fun;
(* pFun)(2,2);
}只有typedef还无法使用,因为未对其进行赋值。函数的函数名,实际上就是一个指针,指向该函数的代码在内存中的首地址。

在C++类中使用函数指针。
typedef返回类型(类名::*新类型)(参数表)
classCA{
public:
char lcFun(int a){return;}};
CA ca;
typedef char(CA::*PTRFUN)(int);
PTRFUN pFun;
voidmain()
{
pFun=CA::lcFun;
ca.(*pFun)(2);
}
在这里,指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是那个类的这里的类对象也可以是使用new得到的。比如 CA*pca=new CA;
pca->(*pFun)(2);
delete pca;
而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。比如:
类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
(this->*m_pFun)(2);
}
一句话,使用类成员函数指针必须有“->*”或“.*”的调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值