我们可以将特定签名的函数地址放入一个函数指针中,该指针被定义为具有其他签名并无缝地使用它吗?
例如,以下代码
#include <stdio.h>
void print_n(int *pn) {
printf("%d\n", *pn);
}
void print_n_wrapper(void *p) {
print_n(p);
}
int main(void) {
int n = 123;
void (*f)(void *) = print_n_wrapper;
f(&n);
f = print_n;
f(&n);
return 0;
}
编译并在我的机器上运行正常。我是以某种方式调用未定义的行为吗?
答案 0 :(得分:8)
是的,它是undefined behaviour。
引用C11
,章节§6.3.2.3,指针,(强调我的)
指向一种类型的函数的指针可以转换为指向另一种函数的指针 打字再回来;结果应该等于原始指针。 如果转换了 指针用于调用类型与引用类型不兼容的函数, 行为未定义。
关于“类型不兼容的功能”部分,兼容性的定义类似于
要使两种函数类型兼容,两者都应指定兼容的返回类型。(146) 此外,参数类型列表(如果两者都存在)应在数量上一致 参数和省略号终止符的使用;相应的参数应具备 兼容类型。
这意味着,void *
和int *
应该是相同的类型,但不是。因此,这些功能也不兼容。
答案 1 :(得分:6)
print_n(p)
中对print_n_wrapper
的调用已定义,因为您所做的只是转换原来为{{1}的void*
到int*
作业int*
会给你带来麻烦。虽然定义 ,但后续调用f = print_n;
的行为未定义。