Can a function pointer with a const argument be used as a function pointer with a nonconst argument?

天大地大妈咪最大 提交于 2019-12-04 00:53:55

You seem to have found something that the compiler writers and standards writers did not account for. From C99 draft n1256, §6.7.5.3 paragraph 15,

corresponding parameters shall have compatible types.

Note that const int * is not compatible with int *. However, int * may be converted to const int *. From §6.3.2.3, paragraph 2,

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type

More sophisticated rules for inferring when it is acceptable to substitute types derived from qualified or unqualified versions of the same type are simply not present in the standard. Therefore, your code is technically in violation of the standard.

My conclusion: It seems to me that this error should be treated as "pedantic" by the compiler: your code does not technically conform to the standard, but the meaning is unambiguous and the code is absolutely safe. Feel free to write a feature request to your compiler vendor. There are plenty of nonconformant practices which do not generate warnings without -pedantic.

As a final note, I compiled with Clang and the compiler informed me that the warning was pedantic. However, I had not requested pedantic warnings... so there appears to be no way to turn it off.

warning: incompatible pointer types passing 'void (int const *)', expected 'void (*)(int *)'
      [-pedantic]

Workaround: Use an explicit cast.

void g(const int *);

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

You are right, there's no reason C should disallow that call (other than because the C standard says it should). U(*)(T*) should be a sub-type of U(*)(const T*) because int* is a sub-type of const int* through substitutability.

Why C does not allow this, I don't know.

As for work-arounds, you can provide a proxy 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)

The fact that using a safe, standard-compliant proxy like this works at all should be proof enough that the call should have been valid in the first place.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!