ctraps 看到了一行神奇的代码:(*(void(*)())0)();

理论准备

一个简单的规则:declare it the way you use it.

每个C声明都包含两部分:类型和一系列表达式。比如:

float f,g;

表示词汇fg在赋值的时候类型是float

因为声明的是表达式,因此可以随意添加括号:

float ((f));

对于函数也是同样的。比如:

float ff();

表示表达式ff()float类型的,因此ff就是一个返回float的函数。

同样的,

float *pf;

代表*pf是一个float,因此pf就是指向一个float的指针。

这些形式结合到一起的时候,和用于表达式的时候的结合方法是一样的。因此

float *g(), (*h)();

含义就是*g() (*h)()float表达式。因为()优先级更高,所以*g()*(g())含义相同:g是一个返回指向float的指针的函数,h是一个指向一个返回float的函数的指针。(是不是有点晕?)

要进行类型转换,只需要声明中的变量名和分号移除就行了。所以float *g()的类型转换是(float *())

理解这行代码

有了上面的理论,现在可以理解(*(void (*) ())0)()了。

首先,假设我们有一个变量fp表示一个函数指针,即:
void (*fp)()

这样这行代码里的(void (*) ())就是到fp这个类型的强制类型转换,可以先不看。接下来是
(*0)(),这里*00地址指向的内存,想让它能运行,必须吧0强制类型转换成(void (*) ())

所以,结论是,这行代码执行了0地址出内存代表的函数。

历史记录

  • 2019-04-27 - 初稿

猜你喜欢


文章标题:奇技淫巧之一行神奇的C代码

文章字数:699

本文作者:转载

发布时间:2019-04-27

最后更新:2019-04-27

原始链接:http://literateprogramming.com/ctraps.pdf

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。