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

ANSI C中给结构体函数指针成员赋值为何要使用特殊指针转换写法?

问题结论

你简化的同类型函数指针场景下,直接赋值完全合法,不需要书中的特殊写法;但原书真实场景下,该写法是符合ANSI C(C89)标准的兼容方案,在老编译环境下有必要性。


原因说明

1. 你简化场景的误区

你自己构造的示例中,foo.function和method确实都是void (*)()类型,同类型函数指针直接赋值是C标准明确支持的操作,完全可以写foo.function = method,书中的写法在这个场景下属于多余操作。

2. 原书场景的本质差异

原书的真实代码里,method的类型是作者自定义的通用函数指针voidf,也就是void (*)(),但结构体中的ctor、dtor、differ等成员,都是带明确返回值、参数列表的不同类型函数指针,和voidf不属于兼容类型:

  • ctor的类型是void * (*)(const void *, va_list *)
  • dtor的类型是void * (*)(const void *)
  • 均和void (*)()类型不兼容

3. ANSI C的约束规则

ANSI C(C89)标准中,不同类型的函数指针直接赋值属于未定义行为,很多老编译器会直接抛出类型不兼容的错误,同时标准也不允许void *和函数指针互相转换(部分平台函数指针长度和数据指针长度不同),所以作者没有用void *做通用载体,而是自定义了voidf作为通用函数指针类型。

书中用*(voidf *) &self->ctor = method的写法,本质是:

  • 先取函数指针成员的内存地址
  • 强制转换为voidf类型的指针
  • 解引用后完成赋值
    这个操作绕开了编译器的类型检查,直接将method的二进制内容逐位拷贝到成员的内存空间中,避免了不同类型函数指针直接赋值的编译错误和标准未定义问题。

4. 现代环境的差异

如果是C99及之后的C标准,已经明确允许不同函数指针之间互相转换,只要调用时使用正确的类型即可,在大部分现代编译器下直接写self->ctor = (typeof(self->ctor))method或者甚至不加强转都能正常运行。但原书是针对ANSI C标准编写的,要兼容老编译环境,所以采用了更保守的写法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:45:02