带有const参数的函数指针是否可以用作带有nonconst参数的函数指针?

也许标题本身并不清楚……我有一个函数f(由某些库提供),它将一个函数指针作为参数作为签名void g(int*) ,即ie

 void f(void (*g)(int*)); 

但是,我想使用函数g (我定义)和签名void g(const int*)来使用它。 先验,我无法看到这是如何违反任何const正确性的,因为f所有签名都表示g只会被一个(非constint* (非常量)调用,事实上我可以使用非const int*参数调用void (const int*)函数。

但海湾合作委员会抱怨并说,

 expected 'void (*)(int *)', but argument is of type 'void (*)(const int *)' 

我看不出这个投诉是如何合法的,所以有人知道我对此的理解是否错误,或者是否有办法解决?

您似乎找到了编译器编写者和标准编写者未考虑的内容。 从C99草案n1256,§6.7.5.3第15段,

相应的参数应具有兼容的类型。

请注意, const int *int *不兼容。 但是, int *可能会转换为const int * 。 从§6.3.2.3第2段开始,

对于任何限定符q ,指向非q限定类型的指针可以转换为指向该类型的q限定版本的指针

用于推断何时可以替换从相同类型的合格或非限定版本派生的类型的更复杂的规则在标准中根本不存在。 因此,您的代码在技术上违反了标准。

我的结论:在我看来,这个错误应该被编译器视为“迂腐”:你的代码在技术上并不符合标准,但意思是明确的,代码是绝对安全的。 随意向您的编译器供应商写一个function请求。 有很多不符合要求的做法,如果没有-pedantic ,就不会产生警告。

作为最后一点,我和Clang一起编辑,编辑告诉我警告是迂腐的。 但是,我没有要求迂腐警告……所以似乎无法将其关闭。

警告:不兼容的指针类型传递'void(int const *)',expected'void(*)(int *)'
       [-pedantic]

解决方法:使用显式强制转换。

 void g(const int *); f((void (*)(int *)) g); 

你是对的,没有理由C不应该禁止这个电话(除了因为C标准说它应该)。 U(*)(T*)应该是U(*)(const T*)的子类型,因为int*是通过可替代性的const int*的子类型。

为什么C不允许这样,我不知道。

至于解决方法,您可以提供代理function:

 void foo(const int* x) { ... } // <-- the function you want to pass in void bar(int* x) { foo(x); } // proxy f(bar); // instead of f(foo) 

使用像这样的安全,符合标准的代理工作的事实应该足够certificate该调用本来应该是有效的。