一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
13.两个奇葩代码
代码1: (*(void(*)())0)()
*void(ptr)()
ptr是函数指针,指向的函数返回类型为void,无参数
ptr的类型为:void(*)()
double a = 10.0; int b = 0;
b = (int)a; //把a强转为int类型赋给b
在变量的前面加一个类型->强制类型转换
注意:强制类型转换并不会改变变量存放在内存中的内容,只是改变了如何读取变量的内存中的内容的方式
(*(void(*)())0)()
//void(*)() -函数指针
解析:这是一次函数调用
1.代码中把0强制类型转换为类型为void(*)()的一个函数的地址
2.解引用0地址的内容,就是取0地址处的这个函数,被调用的这个函数是无参的,返回类型是void
例如:
printf("%p\n",Add);//假设Add函数的地址为:0x0012ff40, 该地址处放着一个参数为int,int,返回类型为int的函数,
代码2:void (*signal(int,void(*)(int)))(int)
分析1:
signal先和()结合->signal是函数,signal函数有两个参数,第一个是int类型,第二个是void(*)(int)类型的函数指针
去掉函数名和函数的参数->就是函数的返回类型
例如: int Add(intx,int y) ->去掉函数名和函数的参数->int
所以把signal函数的函数名和参数去掉-> void(*)(int)
所以signal函数的返回类型是函数指针类型
解析:这是一次函数声明,声明的函数名是signal
signal函数有两个参数,第一个是int类型,第二个是void(*)(int)的函数指针类型,
signal函数的返回类型是一个 void(*)(int)的函数指针类型
将代码2改造简洁-typedef
typedef void(*pfun_t)(int); //这样写才是正确的,pfun_t == void(*)(int) 函数种子很类型
typedef void(*)(int) pfun_t; // err 语法不支持
//语法规定:要把重命名的名字放在*里
所以void (*signal(int,void(\*)(int)))(int)可以简化成: pfun_t signal (int,pfun_t);
一个参数为函数指针类型,一个参数为int类型,返回类型为函数指针类型
14.指向函数指针的数组
int* arr[10]; //存放整形指针的数组
//函数指针数组->存放函数指针的数组
int Add(int x,int y)
{
return x+y;
}
int Sub(int x,int y)
{
return x-y;
}
int Mul(int x,int y)
{
return x*y;
}
int Div(int x,int y)
{
return x/y;
}
int main()
{
int(*pf1)(int,int) = Add;
int(*pf2)(int,int) = Sub;
int(*pf3)(int,int) = Mul;
int(*pf4)(int,int) = Div;
//pfArr就是一个函数指针数组
int(*pfArr[4])(int,int) = {Add,Sub,Mul,Div};
//pfArr先和[]结合->是数组
//去掉数组名和元素个数->元素类型为:int(*)(int,int) 是一个函数指针,指向的函数的参数为int,int,返回类型为int
//使用:
int ret = pfArr[0](2,3);
//也可以写成: int ret = (*pfArr[0])(2,3);
// pfArr[0] == pf1 ==Add == *(pfArr[0]) ==(*pf1)
printf("%d\n",ret); //5
return 0;
}