一对指向不同函数的指针可以兼容不同类型的参数吗?

时间:2015-07-24 11:41:35

标签: c function-pointers language-lawyer undefined-behavior

我们可以将特定签名的函数地址放入一个函数指针中,该指针被定义为具有其他签名并无缝地使用它吗?

例如,以下代码

#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;
}

编译并在我的机器上运行正常。我是以某种方式调用未定义的行为吗?

2 个答案:

答案 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; 的行为未定义。