C语言经典案例 void (*signal(int sig, void (*func)(int)))(int) 解读,带你学习函数名的本质,函数指针与指针函数,以及回调

编程入门 行业动态 更新时间:2024-10-09 05:18:54

C语言经典案例 void (*signal(int sig, void (*func)(int)))(int) 解读,带你学习<a href=https://www.elefans.com/category/jswz/34/1771370.html style=函数名的本质,函数指针与指针函数,以及回调"/>

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); 函数指针

函数指针是需要把一个函数的地址赋值给它,有两种写法:

  1. fun = &Function;
  2. fun = Function;

取地址运算符&不是必需的,因为一个函数标识符就表示了它的地址,如果是函数调用,还必须包含一个圆括号括起来的参数表。
调用函数指针的方式也有两种:

  1. x = (*fun)();
  2. 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) 解读,带你学习函数名的本质,函数指针与指针函数,

本文发布于:2024-03-13 01:06:09,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732834.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   指针   带你   回调   本质

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!