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
相关产品推荐
相关产品推荐

