对C语言中(*(void(*))0)()的理解

一、(*(void(*))0)()的理解。
导论:在一些复杂的代码工程中,经常出现类似于(*(void(*))0)()这种复杂的表达式,今天就带大家慢慢剖析这种表达式,教大家理解。

1.一个函数名的本质。
函数名的实质就是一个函数的首地址,当执行这个函数的时候,其实就是跳转到相应的地址去执行这个地址下装的二进制代码,可以通过以下程序了解:

#include <stdio.h>
int (*test)(int);
int Print(int num)
{
    printf("The num is %d\n",num);
}
    int main()
{
    test = Print;       
    (*test)(1);
    printf("The addr is %p\n", test);
    (*(int(*)())0x804841d)(2);
} 

运行的结果是:

The num is 1 
The addr is 0x804841d
The num is 2

对代码的分析:

  1. 首先通过int (*test)(int)定义一个int(*)类型的函数指针,然后将Print函数(实质上是一个地址)放到指针变量test中去,所以当执行(*test)(1)的时候实质上就执行了Print(1)。

  2. 其次,通过直接打印test这个指针变量可发现这个这个函数的首地址是0x804841d。

  3. 最后,为了证实这个地址是函数的首地址,所以我们把这个地址用强制转换成为int(*)()类型的函数指针,也就是(int(*)())0x804841d,最后,若是要引用这个函数,就必须对函数指针解引用,也就是(*fuc)(2),而这里的fuc指针就是(int(*)())0x804841d,所以(*(int(*)())0x804841d)(2)的意思就是将这串地址强制转换成为int(*)()类型的函数指针,然后再对这个指针解引用执行而已!

如此,(*(void(*))0)()这个问题的解析也同上了,(void(*))0实质就是将0地址强制转换成为void(*)类型的函数指针,然后再对这个指针解引用,也就变成了(*(void(*))0)()了。

二、使用Typedef对复杂指针变量的重命名。
1.Typedef的重命名类型可以使得函数指针的定义变得更加方便以及容易,而函数指针的重命名规则为如:

typedef int (*pF)(int);

此句的意思为将pF重命名为一个int(*)(int)的类型,所以上面的代码用重命名方式改写可得:

#include <stdio.h>
typedef int (*pF)(int);
int Print(int num)
{
    printf("The num is %d\n",num);
}
    int main()
{
    pF test = Print;
    (*test)(1);
    printf("The addr is %p\n", test);
    (*(pF)0x804841d)(2);
}

解析:

  1. pF test = Print使用重命名以后可以直接pF定义test为int(*)(int)类型,并且将Print函数赋值到函数指针test中去,而后面的(*(int(*)())0x804841d)(2)可以变成(*(pF)0x804841d)(2)也比之前的简单许多,由于pF类型就是int(*)(int)类型,所以只需将这个地址强制转换成为pF类型并且解引用即可。

  2. 因此,(*(void(*))0)()也可以进行如下进行简化:

     typedef void (*pF)();
    (*(pF)0)();
  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值