闲着无聊不想敲代码,那就没事复复习吧。突然想到这个的原因是因为想起来自己之前看过的一个东西,首先来看这么一个 C 语言语句。
1 | (*(void(*)())0)(); |
如果你之前并没有了解过或者了解函数指针的话,那么肯定会和我刚开始看到一样是懵逼的,这篇文章将围绕这个来介绍函数指针。
首先说清楚,这是一个函数的调用,算是一个经典的例子,并且和那种纠结于 ++i 和 i++ 的 i++++++i 这种例子不同,这是一个在微处理器上比较常用的语句。某些微处理器我们需要从 0 地址启动,或者有时需要模拟开机启动的情形,需要去设计这么一条语句用来执行 0 地址的内存里的内容(所以这条语句不是为了秀操作而来的哦)。
在此我假设你对函数指针有一定的概念,或者对指针有一定的概念。
函数指针,即指向函数的指针。一般定义语句如下:
1 | void (*pFun)(param); |
我们定义函数是 void fun(param)
,函数指针也只是加了一个指针符号而已。而我们定义了函数指针之后,调用如下:
1 | (*pFun)(param); |
现在我们来看我们的神奇语句: (*(void(*)())0)();
,这是一个函数调用,所以我们可以将其分为两部分,我们以上边的函数调用为例将其看成 (*pFun)(param)
,那么其实 (void(*)())0
其实就是我们 pFun
的部分。
那么 (void(*)())0
这一串看起来很让人不爽的又是该如何理解呢,如果你还没看出来的话可以试着想想,有什么东西是 (...)..
的形式呢?
这是一个强制转换的语句,我们刚才说了,这个例子是用来执行 0 地址的内存的内容,如果直接写的话应该是这样:
1 | (*0)(); |
这就是调用 0 地址里边的内容执行的语句,但是函数指针变量又不能是个常数,我们需要对其进行转换,与时就成了 (*(void(*)())0)()
这个样子。所以这个语句的意思就分析出来了,其实是将一个 0 地址强制转换成 void(*)()
函数指针的形式,然后去执行。
现在,我们将其改成比较简单可以理解的形式:
1 | typedef void(*pFun)(); // 为 void(*)() 定义别名 pFun; |
这样,应该可以看得很清楚了。如果你没懂 typedef void(*pFun)();
,建议去看看 typedef
在 C 语言中的用法。