函数名的本质,函数指针与指针函数,以及回调"/>
C语言经典案例 void (*signal(int sig, void (*func)(int)))(int) 解读,带你学习函数名的本质,函数指针与指针函数,以及回调
目录
- 案例解读
- 1 函数指针与指针函数
- 1.1 指针函数
- 1.2 函数指针
- 2 解析void (*signal (int sinno,void(*func)(int)))(int)
- 3 函数指针与回调
- 3.1 ((void (*)(void))0x00401340)() 通过地址调用函数
- 3.2 例程2
- 3.3 用来解释例3.1和例3.2的C语言代码
- 3.4 多种玩法
案例解读
函数: void (*signal (int sinno,void(*func)(int)))(int)
上述函数该如何读呢? 那么先了解下面的一组概念
1 函数指针与指针函数
指针函数:
本质是一个函数,其返回值为指针。
函数指针:
本质是一个指针,其指向一个函数。
如果想详细更进一步的了解,可以参考下述文章: 函数指针和指针函数用法和区别
1.1 指针函数
指针函数:
简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针
以下示例:
int fun(int x,int y);
这种函数应该都很熟悉,其实就是一个函数,然后返回值是一个 int 类型,是一个数值int *fun(int x,int y);
这个函数就是一个指针函数。其返回值是一个 int 类型的指针,是一个地址。
总结: 指针函数和普通函数对比不过就是其返回了一个指针(即地址值)而已
1.2 函数指针
函数指针:
其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
以下示例:
int fun(int x,int y);
普通函数int *fun(int x,int y);
指针函数int (*fun)(int x,int y);
函数指针
函数指针是需要把一个函数的地址赋值给它,有两种写法:
fun = &Function;
fun = Function;
取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
调用函数指针的方式也有两种:
x = (*fun)();
x = fun();
两种方式均可,看个人习惯,如果理解其定义,随便怎么用都行
2 解析void (*signal (int sinno,void(*func)(int)))(int)
void (*signal(int sig, void (*func)(int)))(int) void (*func)(int) = A
func 是一个指向函数的指针--该函数以int作为入参,返回值为空 signal(int sig, void (*func)(int)) = B
signal 是一个函数-- 该函数有两个参数(一个是int型变量 sig 一个是指向函数的指针A)void (*B)(int)
B是一个函数,返回值是一个指向函数(入参为int 返回值为空)的指针 signal 是一个函数-- 该函数有两个参数(一个是int型变量 sig 一个是指向函数(该函数以int作为入参,返回值为空 )的指针) ,signal的返回值是一个指向函数(入参为int 返回值为空)的指针
3 函数指针与回调
函数指针,一般用途作为“回调函数”使用。
比如写了一个方法(函数),你希望调用它执行完处理之后,自动调用另一个后续的函数来处理继续的业务。
这个时候就可以把 “一个函数的入口地址”当是一个指针。 你的处理方法中接受函数参数时把这个指针传进来。
// 指针函数
int *myPlus(int a, int b)
{printf("plus:%d + % d = %d\n" ,a ,b, a + b );return 0;
}
int *myMinus(int a, int b)
{printf("minus: %d - % d = %d\n", a, b, a - b);return 0;
}//参数funtz
int funt2( int a, int b , void *funtz)
{//pf为函数指针,int(*pf)(int, int) = ( int (*)(int,int ) )funtz;pf(a, b);return 0;
}//主函数入口
int main()
{funt2(10,20, myPlus); //myPlus 是一个函数指针,它现在是作为一个参数在传递funt2(10,20, myMinus);return 0;
}
函数
: 本质是一段可执行代码段。函数名:
指向这段代码段的首地址。
函数在内存中是有地址的,函数名对应着函数的首地址,既然有地址,就可以定义指针储存地址或更改指针的指向,存储函数(首)地址的指针,称为函数指针
3.1 ((void (*)(void))0x00401340)() 通过地址调用函数
#include<stdio.h>
void print()
{printf("调用了print函数\n");return;
}int main()
{((void (*)(void))0x00401340)();return 0;
}
结果:
调用了print函数
3.2 例程2
#include<stdio.h>
int main()
{int a=100;//a的地址是0x0061fefcprintf("打印a:%d\n",*(int*)0x0061fefc);return 0;
}
结果:
打印a:100
3.3 用来解释例3.1和例3.2的C语言代码
#include<stdio.h>
void print()
{printf("调用了print函数\n");return;
}
int main()
{int a=100;printf("第一次打印a:%d\n",a);printf("a的地址是:%p\n",&a);//a的地址是0x0061fefcprintf("第二次打印a:%d\n",*(int*)0x0061fefc);printf("\n");print();printf("print的地址是:%p\n",print);//print()的地址是0x00401340((void(*)(void))0x00401340)();return 0;
}
结果:
第一次打印a:100
a的地址是:0061fefc
第二次打印a:100调用了print函数
print的地址是:00401340
调用了print函数
3.4 多种玩法
#include<stdio.h>void print()
{printf("调用了print函数\n");return;
}int main()
{//void (*p)(void)函数类型的基本格式//第一种玩法((void (*)(void))0x00401340)();//第二种玩法void (*p1)(void)=print;p1();//第三种玩法(不推荐)void (*p2)(void)=&print;(*p2)();//第四种玩法typedef void (*PF)(void);PF pf=print;pf();return 0;
}
结果:
调用了print函数
调用了print函数
调用了print函数
调用了print函数
更多推荐
C语言经典案例 void (*signal(int sig, void (*func)(int)))(int) 解读,带你学习函数名的本质,函数指针与指针函数,
发布评论