关于C的指针函数,函数指针,函数指针数组调用的一些理解

今天去面试,出了一个题目是用C跳转到0x00000000的位置。居然忘记了,晚上回来看一下,再一次彻底理解,希望不要再忘记了!特写下此篇来帮助大家理解

1指针函数:

指针函数从字面上理解就是一个带指针的函数。如 定义一个指针函数 int * test(int* x ) 就这么简单,最常见的一个函数就是malloc()函数啦,不要跟我说你不知道。

2函数指针:

函数指针本质是指针,然后可以跳到该地址执行。如 定义一个指针函数 int (*test)(int *)。这里的意思是将test定义为一个函数的指针,这个指针的指向的类型是参数是一个int*类型,返回值为int类型的函数。是不是和前面的指针函数很像,但是请看括号的位置,指针函数的*是和int结合,函数指针的*是和test结合。

有了上面的基础,我们可以开始将这个题目了,按照上面说的,我们可以定义一个函数指针P,然后把0x00000000赋值给P即可。如下:

void (*p)(void) = 0x00000000;

(*p)();

那我如何做到将其写成一步的形式呢?将0x0000000直接强转成某类型的函数指针,并跳转呢?

好我们先看看强转是怎么定义的,先几个简单的,比如:(char*)(data) ,        (int*)(data) ,    (long)(data)有没有发现什么规律?

其实强转某类型时就是将定义某类型的数据时,删除变量的名,并加上括号。举例如果是char *类型,你定义的时候是char * data, 如果是将 data强转成char *型呢?当然是

(char *)(data)了,明白我的意思了么?

我再来看一下如何强转函数指针,同理我们定义的时候是这样的void (*p)(void) ,那根据上面的规律强转就是将p这个变量去掉,加上括号。因此就变成了

(void(*)(void))(data),然后我们把data这个东西用0x0000000带入,于是就变成了(void(*)(void))(0x00000000)。好了0x00000000顺利转成了函数指针了,接下来就是执行它了

就相当于(*p)()这一步了。同理将上面那一部分东西代入即可。于是得到最终的形式是:(*(void(*)(void))(0x00000000))();大功告成。但是很多时候如果参数是void类型时,参数里的void可以不用写。所以大家可以看到常见的写法都是这样:(*(void(*)())(0x00000000))();但是如果是如果有参数值时,就必须将加上参数的类型。如 

int (*test)(int *)

3函数指针数组

这个鸟东西一般情况下都见不到,但是在linux内核中,经常用它来做按照顺序初始化工作。最近也在学习linux内核就顺便讲讲。其实了解了函数指针以后就不难了,其实就是一个数组,里面存的都是一群函数的地址而已。那如何定义呢?

按照数组的定义方式应该是int data[];这样就可以了,那我们现在按照我们说的依样画葫芦。如果我定义的函数类型时 int (*p)(int,int);

那我们就可以写出函数指针数组方式应该是:int (*init[])(int,int);假设我定义的数组名字叫init。注:测试在linux下用gcc时,必须指定init的数组长度

好,我在linux写了个测试代码,来测试实现及调用过程,现在贴出代码来

  1 #include<stdio.h>
  2 
  3 int add(int x,int y)
  4 {
  5         printf("%d\n",(x+y));
  6         return x+y;
  7 }
  8 int dec(int x,int y)
  9 {
  10         return x-y;
  11 }
  12 int main()
  13 {
  14         int (*init[2])(int ,int);
  15         int z;
  16         init[0] = add;
  17         init[1] = dec;
  18         z=(*init[1])((*init[0])(3,4),2);
 19         printf("%d\n",z);
 20         return 0;
 21 }

如果再配合枚举,就可以模拟出linux内核中的函数形式了。数组里1,2的地方就可以用名字代替,增加可读性。这里就不举例了。

好了,就讲到这里了,如有任何疑问和错误,请联系我。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值