理解(*(void(*)())0)();

先说一下强制转换,可以跳过。例子:
#include <stdio.h>
#include <stdint.h>
int main()
{
    uint16_t a = 0xA5A1;
    uint8_t   b;
    b = (uint8_t)a;    // 16位强制转换为8位
    printf("b=0x%X",b); 
}

a是16位,b是8位,将a进行一次强制转换的结果给b。
我这里的输出结果是
b=0xA1
---------------------------------------正文----------------------------------------

include <stdio.h>

void funa(void)
{
	printf("funa is called\n");
}

int main()
{
	void (*p)();	// 定义一个函数指针
	p=funa;		    // p中存放funa函数地址 
	(*p)();		    // 运行funa 
	printf("0x%X",&funa); // 打印funa函数的地址 
	return 0;	
}


我这里执行之后得到的结果是
funa is called
0x401530


第一行表示funa函数已经执行
第二行表示funa函数的地址为0x401530(在不同机器不同时间结果可能都不同)

以这里的结果为例,此时将上述代码的第11、12行改为
p=0x401530;
(*p)();

运行结果是相同的。

但是将11、12行合并为:
(*0x401530)();
编译器会报错。

也就是说,我们需要将 "0x401530"强制转换为函数地址
参照最开始的强制转换,这里的格式应该大体是这样的:
(*(_______)0x401530)();

接下来只需要考虑下划线里该填什么了
参照之前的
void (*p)();     // 定义一个函数指针
我们可以知道,下划线里应该写
void (*)()

那么结果就出来了,这里要想将11、12行合并为一句,只需要这么写:
(* (void (*)())0x401530)();

我这里修改之后的最终程序为:
#include<stdio.h>

void funa(void)
{
	printf("funa is called\n");
}

int main()
{
	(*(void(*)())0x401530)();	// 运行位于0x401530地址处的funa函数 
	printf("0x%X",&funa); 		// 打印funa函数的地址 
	return 0;	
} 

输出和之前是完全相同的。

--------------------------------------归题--------------------------------------
如果我们需要运行位于0地址处的函数(或者是从0地址处开始运行)
只需把上面的0x401530改成0即可
也就是
(*(void(*)())0)();
---------------------------------------拓展----------------------------------------
如果真的理解之后,可以配合typedef使用。
之前的例子可以这样写
#include<stdio.h>
typedef void (*funcptr)();    // 为函数指针类型定义别名funcptr

void funa(void)
{
	printf("funa is called\n");
}

int main()
{
	(*(funcptr)0x401530)();	// 运行位于0x401530地址处的funa函数 
	printf("0x%X",&funa); 	// 打印funa函数的地址 
	return 0;	
} 


参考资料: <C的陷阱与缺陷> 2.1章 Andrew Koenig著

猜你喜欢

转载自kiolp.iteye.com/blog/2247142
今日推荐