传递`int(*)(char const*)`其中`int(*)(char*)`是预期的

PSk*_*cik 6 c pointers function-pointers

我有一个函数指针,其函数被声明为期望char *参数.对于它,我想保存一个指向声明为接受char const*参数的函数的指针.

我想我可以使用包装器或演员.强制转换似乎更直接,但我可以合法地调用这样的函数指针的结果吗?

示例代码如下:

static int write_a(char * X){
    return 0;
}

static int write_b(char const* X){
    return 0;
}
static int wrapped_write_b(char * X){
    return write_b(X);
}

typedef int (*write_fn)(char * );

write_fn a = write_a;
write_fn b = wrapped_write_b;
write_fn b1 = (write_fn)write_b; //is b1 legally callable?
Run Code Online (Sandbox Code Playgroud)

Hol*_*olt 10

这是未定义的行为 - 只有在类型兼容的情况下(6.3.2.3/8),才能使用指针调用其他类型的函数:

指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次返回; 结果应该等于原始指针.如果转换的指针用于调用类型与引用类型不兼容的函数,则行为未定义.

两个函数具有兼容类型,如果(简化版本)它们具有相同的返回值并且参数是兼容的(6.7.6.3,Semantics/15):

对于要兼容的两种函数类型,两者都应指定兼容的返回类型.146)此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用中一致; 相应的参数应具有兼容的类型.

A const char *char *(6.7.6.1,Semantics/2)不兼容:

要使两个指针类型兼容,两者都应具有相同的限定条件,并且两者都应是兼容类型的指针.

由于const char *char *不相同的资格,他们是不兼容的,并呼吁write_b通过b是不确定的行为.


Lun*_*din 3

严格来说,这是不允许的。

Apointer-to-something与 a 不兼容pointer-to-qualified-something。因为 apointer-to-qualified-something不是合格的类型pointer-to-something

这同样适用于

pointer-to-function-accepting-something

pointer-to-function-accepting-qualified-something

这个可以通过C11 6.2.7兼容类型找到:

如果两个类型的类型相同,则它们具有兼容类型。用于确定两种类型是否兼容的附加规则在类型说明符的6.7.2中描述,在类型限定符的6.7.3中描述...

其中6.7.3是相关部分。它说

为了使两个合格类型兼容,两者都应具有兼容类型的相同合格版本;

转换章节6.3.2.3与此并不矛盾:

指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应等于原始指针。如果转换后的指针用于调用其类型与引用类型不兼容的函数,则行为未定义。

编辑

正如 Holt 在回答中指出的,两个函数的兼容性在6.7.6.3/15中有明确描述。


我仍然认为包装函数是最好的解决方案。问题的根源在于write_aconst 不正确。如果您无法更改该函数,请围绕它编写一个包装器。