如何解释从函数指针数组调用C函数?解析混淆语法
拆解函数指针数组的混淆调用语法
先看代码的核心意图
这段代码本质是通过手动计算数组元素地址的方式,从funarray数组中取出第3个元素(索引2)存储的MyFun函数地址,然后调用该函数。下面分步拆解关键逻辑:
1. 计算目标元素的地址
size_t CallMyFun = (size_t)&funarray + (2 * sizeof(funarray[0]));
&funarray是整个数组的首地址,类型为void*(*)[5](指向含5个void*元素的数组的指针)。sizeof(funarray[0])是单个void*元素的大小(通常是4或8字节,取决于平台)。2 * sizeof(funarray[0])是跳过前2个元素的偏移量,加上数组首地址后,得到的就是funarray[2]的内存地址(也就是存储&MyFun的那个元素的地址)。- 最后把这个地址转换成
size_t类型存储,相当于用整数保存了内存地址。
2. 混淆的函数调用语句拆解
核心调用语句是:
(*((int(**)(void))CallMyFun))();
我们从内到外逐层解析:
第一步:强制类型转换
(int(**)(void))CallMyFun
把CallMyFun保存的内存地址,强制转换成int(**)(void)类型——这个类型表示「指向返回值为int、无参数的函数指针的指针」。原因是funarray[2]本身是一个void*,它指向的是MyFun的地址(也就是一个函数指针int(*)(void)),所以CallMyFun是funarray[2]的地址,自然就是「指向函数指针的指针」。第二步:解引用得到函数指针
*(...)
对上面的「指向函数指针的指针」解引用,就得到了funarray[2]存储的内容——也就是MyFun的函数指针,类型为int(*)(void)。第三步:调用函数
(...)()
用函数指针调用对应的函数,执行MyFun的逻辑,输出"Hello, World!"并返回0。
简化写法说明
其实在C语言中,函数指针调用时可以省略解引用操作*,所以这段混淆代码可以简化成更易读的版本:
// 直接转成函数指针后调用 ((int(*)(void))*(void**)CallMyFun)(); // 或者更直白的写法(先取出数组元素) int(*fp)(void) = (int(*)(void))funarray[2]; fp();
另外要注意:标准C中void*并不保证能安全转换为函数指针,这段代码是依赖编译器的扩展支持才能正常运行。
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

