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

后端 未结 2 1051
野趣味
野趣味 2021-02-19 00:36

Perhaps the title isn\'t clear in itself... I have a function f (provided by some library) that takes as an argument a function pointer of signature void g(int*), i

相关标签:
2条回答
  • 2021-02-19 01:34

    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.

    0 讨论(0)
  • 2021-02-19 01:35

    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);
    
    0 讨论(0)
提交回复
热议问题