当前位置:文档之家› 将0转型为“指向返回值为void的函数的指针” (void (x)())0

将0转型为“指向返回值为void的函数的指针” (void (x)())0

(void (*)())0 的含义(void (*)())0 的含义:1. fp是一个指针{有*},她指向返回值为void{有(void)}类型的函数{有()}:void (*fp)();调用方式简写为:(*fp)();2. 制作其对应的类型强制转换符:void (*)()3. 存储位置为0 的强制转换为一个指向返回值为void类型的函数的指针:(void (*)())04. 用上式代替fp,从而实现调用存储位置为0的子例程:(*(void(*)())0)();5. 利用typedef简化:typedef void (*funcptr)(); (*(funcptr)0)();(void (*)())0 的含义:实际上就是将地址0强制转换为一个指向返回值为void类型的函数的指针。

下面将相关基础知识进行介绍,其中参考了网上一些文章,名单不再列出,谢谢各位大虾的贡献:1、c语言的声明2、类型转换符的制作3、signal函数分析4、typedef用法5、const用法6、typedef的好处1 C语言的声明声明由两部分组成:类型以及声明符:float f,g;float ((f));//对其求值时,((f))的类型为浮点型,可以推知,f也是浮点型float *g(),(*h)();//g是函数,该函数的返回类型为指向浮点数的指针//h是个指针,且是一个函数指针,该指针指向函数返回值,该返回值是一个float型(*fp)()简写为fp()//函数调用方式,其中fp为函数指针*((*fp)())简写为*fp()//函数返回值为某个类型的指针、2 类型转换符制作类型转换符制作:1、去掉声明中的变量名、分号;2、将剩余部分用括号"封装"起来float (*h)(); --> (float (*)())//指向返回值为float型的函数指针的类型转换符(*0)();//返回值为void类型的函数指针如果fp是一个指向返回值为void类型的函数的指针,那么(*fp)()的值为 void,fp的声明如下:void (*fp)();因此可以用下式完成调用存储位置为0的子例程:void (*fp)(); (*fp)();这种写法的代价是多声明了一个哑变量,我们常将0转型为“指向返回值为void的函数的指针”:(void (*)())0用上式代替fp,从而得到:(*(void(*)())0)();typedef void (*funcptr)();将0转型为“指向返回值为void的函数的指针”-----(void (*)())0(*(funcptr)0)();3 signal函数signal函数接受两个参数:信号类型的整型值、指向用户提供的信号处理函数指针用户提供的信号处理函数返回值类型为:voidsignal的返回值类型:指向调用前的用户定义信号处理函数的指针下面分析 signal函数在signal.h中是如何声明的1. 用户定义信号处理函数:void sigfunc(int n){/*特定信号处理部分*/}2. sigfunc声明:void sigfunc(int);3. 假设sfp指向sigfunc函数,sigfunc函数声明:void (*sfp)(int);4. 假设sig为一整数,则 (*sfp)(sig)返回值为void类型5. sfp与signal返回值类型相同,故声明signal函数:void (*signal(something))(int);//something 为signal的参数类型//过程分析:传递一个适当的参数调用signal;对signal的返回值解引用;传递一个参数调用解引用后(void (*)())0将0转型为“指向返回值为void的函数的指针”-----(void (*)())0//得到的函数;得到返回值为void型//signal函数返回值是一个指向返回值为void类型的函数的指针6. signal其中参数为:int 、 void (*)(int),故signal函数:void (*signal(int,void(*)(int)))(int);7. 用typedef简化: typedef void (*HANDLER)(int); HANDER signal(int,HANDER);将0转型为“指向返回值为void的函数的指针”-----(void (*)())04 typedef用法例1:int* (*a[5])(int, char*);typedef int* (*PF)(int, char*);//PF是一个类型别名PF a[5];//跟int* (*a[5])(int, char*);的效果一样!//很多初学者只知道typedef char* p char;但是对于typedef的其它用法不太了解。

//Stephen Blaha对typedef用法做过一个总结:“建立一个类型别名的方法很简单,//在传统的变量声明表达式里用类型名替代变量名,然后把关键字 typedef加在该语句的开头”。

例2:void (*b[10])(void (*)());typedef void (*pfv)();typedef void (*pf_taking_pfv)(pfv);pf_taking_pfv b[10]; //跟void (*b[10]) (void (*)());的效果一样!例3:double(*)()(*pa)[9];typedef double(*PF)();const和volatile在类型声明中的位置。

5 const用法(volatile是一样的)volatile修饰的量就是很容易变化,不稳定的量,它可能被其它线程,操作系统,硬件等等在未知的时间改变,所以它被存储在内存中,每次取用它的时候都只能在内存中去读取,它不能被编译器优化放在内部寄存器中。

const int; //int是constconst char*;//char是constchar* const;//*(指针)是constconst char* const;//char和*都是const另外一个对等的写法(const在后面):int const; //int是constchar const*;//char是constchar* const;//*(指针)是constchar const* const;//char和*都是constconst在后面有两个好处:A.const所修饰的类型正好是在它前面的那一个B.用到typedef的类型别名定义时,如typedef char* pchar,当const在前面的时候,就是const pchar,它的真实含义是char* const,而不是const char* 。

将0转型为“指向返回值为void的函数的指针”-----(void (*)())06 typedef的好处使用 typedef 来编写更美观和可读的代码。

所谓美观,意指typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性,使代码更健壮。

typedef使用最多的地方是创建易于记忆的类型名,用它来归档程序员的意图。

类型出现在所声明的变量名字中,位于typedef关键字右边:typedef int size;注意typedef并不创建新的类型,仅仅为现有类型添加一个同义字,使用 size:void measure(size * psz);size array[4];typedef 可以掩饰复合类型,如指针和数组:char line[81]; char text[81];定义一个typedef,每当要用到相同类型和大小的数组时,可以这样:typedef char Line[81];Line text, secondline;getline(text);同样,可以象下面这样隐藏指针语法:typedef char * pstr;int mystrcmp(pstr, pstr);第一个 typedef 陷阱:标准函数 strcmp()有两个const char *类型的参数。

因此,它可能会误导人们象下面这样声明:int mystrcmp(const pstr, const pstr);const pstr被编译器解释为char * const(一个指向 char 的常量指针),而不是const char *(指向常量 char 的指针)。

这个问题很容易解决:typedef const char * cpstr;int mystrcmp(cpstr, cpstr);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 就像 auto,extern,mutable,static,和 register 一样,是一个存储类关键字。

这并不是说typedef会真正影响对象的存储特性;它只是说在语句构成上,typedef 声明看起来象static,extern 等类型的变量声明。

第二个陷阱:typedef register int FAST_COUNTER; // 错误编译通不过不能在声明中有多个存储类关键字,因为符号 typedef 已经占据了存储类关键字的位置。

在 typedef 声明中不能用 register(或任何其它存储类关键字)。

typedef定义机器无关的类型:例如定义一个叫 REAL 的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL;typedef double REAL;//不支持 long double 的机器上typedef float REAL;//不支持double 的机器上不用修改源代码,便可在每一种平台上编译这个使用 REAL 类型的应用程序。

相关主题