有关指针的两个奇葩代码讲解&&指向函数指针的数组

74 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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

image-20220214210153025

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;
}