看ctraps 看到了一行神奇的代码:(*(void(*)())0)();
理论准备
一个简单的规则:declare it the way you use it.
每个C声明都包含两部分:类型和一系列表达式。比如:
float f,g;
表示词汇f
和g
在赋值的时候类型是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)()
,这里*0
即0
地址指向的内存,想让它能运行,必须吧0
强制类型转换成(void (*) ())
。
所以,结论是,这行代码执行了0
地址出内存代表的函数。