tml*_*len 4 c casting function-pointers
#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
}
Run Code Online (Sandbox Code Playgroud)
函数指针void(*)(A*)被强制转换为函数指针void(*)(void*)。然后使用类型为 的参数调用它A*。
直接使用是否能保证正常工作(1)?还是需要像(2)那样将其投射回来?
tst*_*isl 13
首先。C11 标准 6.3.2.3p8允许指向具有不同签名的函数的指针之间的转换
指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应等于原始指针。
pf(&a);// 1
不。这是未定义的行为,并且不能保证有效。来自C11 标准,6.3.2.3p8:
...如果转换后的指针用于调用其类型与引用类型不兼容的函数,则行为未定义。
((void(*)(A*))pf)(&a);// 2
它很好而且很明确。因为带有签名的函数void(A*)是通过指向 的指针调用的void(A*)。
为了使两个函数类型兼容,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面一致;相应的参数应具有兼容的类型。...
函数void(void*)和void(A*)不兼容,因为类型void*和A*不兼容。