#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)那样将其转换回来?
1条答案
按热度按时间mwg9r5ms1#
首先,C11标准6.3.2.3p8允许指向不同签名函数的指针之间的强制转换
指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次转换回来;结果应与原始指针相等。
方法1
x1月1x// 1
不可以。这是未定义的行为,不能保证一定有效。来自C11标准6.3.2.3p8:
...如果转换后的指针用于调用其类型与引用类型不兼容的函数,则该行为未定义。
方法2
((void(*)(A*))pf)(&a);
// 2它很好,并且定义好了,因为签名为
void(A*)
的函数是通过指向void(A*)
的指针调用的。编辑
函数类型的兼容性在6.7.6.3p15中定义:
要使两个函数类型兼容,两者都应指定兼容的返回类型。此外,如果参数类型列表都存在,则应在参数数量和省略号终止符的使用方面保持一致;相应参数应具有兼容类型...
函数
void(void*)
和void(A*)
不兼容,因为类型void*
和A*
不兼容。