对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)();
发布了24 篇原创文章 · 获赞 27 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gyyu32g/article/details/86428831
今日推荐