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

本文详细介绍了如何在C语言中使用函数指针来调用特定地址处的函数,并通过实例演示了如何直接利用函数地址进行调用的过程。文章还探讨了如何将整数地址强制转换为函数指针类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先说一下强制转换,可以跳过。例子:
#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著
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值