You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

函数指针跨指针类型转换后:直接调用可靠吗?需转回原类型吗?

函数指针转换与调用的合法性问题

先看示例代码:

#include <stdio.h>

typedef struct {
    int i;
} A;

void f(A* a) {
    printf("%d\n", a->i);
}

int main() {
    void (*pf)(void*) = (void(*)(void*))&f;
    A a;
    pf(&a); // 1
    ((void(*)(A*))pf)(&a); // 2
}

问题

把类型为void(*)(A*)的函数指针强制转换成void(*)(void*)后,用A*类型的实参直接调用(标记1处)能否保证正确运行?还是必须像标记2处那样先转回原类型再调用?


答案

必须像标记2那样转回原函数指针类型再调用,才能保证跨平台的正确性与合规性;标记1的直接调用属于未定义行为,标准不保证其能正常运行。

详细说明

  1. C标准的明确规则
    C标准规定:函数指针可以在不同类型之间转换,也可以和void*转换(平台支持的前提下),但只有用与原函数类型兼容的指针调用时,行为才是确定的。原函数f的类型是void(*)(A*),只有用该类型的指针调用,才符合标准要求。

  2. 标记1的潜在风险
    在x86、x86_64这类常见平台上,A*和void*的内存大小、二进制表示完全一致,参数传递规则也相同,所以标记1的代码可能实际跑起来没问题。但这只是平台实现的巧合,不是标准强制要求:

  • 有些特殊平台可能存在不同指针类型大小不同的情况(标准允许这种设计);
  • 编译器会根据函数指针的声明类型做优化假设,标记1的写法可能触发编译器的异常优化,导致参数传递错误、栈帧损坏等不可预期的问题。
  1. 标记2的合法性
    把pf转回原类型void(*)(A*)后再调用,完全符合标准:转换回原类型的函数指针,其值和原指针&f完全相等,调用效果和直接调用&f没有区别。

内容的提问来源于stack exchange,提问作者tmlen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:09:57