杂杂碎碎的常识第一弹-C函数指针

  闲着无聊不想敲代码,那就没事复复习吧。突然想到这个的原因是因为想起来自己之前看过的一个东西,首先来看这么一个 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
2
typedef void(*pFun)();  	// 为 void(*)() 定义别名 pFun;
(*(pFun)0)();

  这样,应该可以看得很清楚了。如果你没懂 typedef void(*pFun)(); ,建议去看看 typedef 在 C 语言中的用法。

0%