I have a function pointer whose function is declared as expecting char *
arguments.Into it, I'd like to save a pointer to a function declared as taking char const*
arguments.
I guess I can either use a wrapper or a cast. Casts seem more straightforward, but can I legally call the result of such a function pointer cast?
Example code below:
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?
This is undefined behavior - You can use a pointer to call a function of another type only if the types are compatible (6.3.2.3/8):
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
Two functions have compatible types if (simplified version) they have same return and arguments are compatible (6.7.6.3, Semantics/15):
For two function types to be compatible, both shall specify compatible return types.146) Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types.
A const char *
is not compatible with a char *
(6.7.6.1, Semantics/2):
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
Since const char *
and char *
are not identically qualified, they are not compatible, and calling write_b
through b
is undefined behavior.
Strictly speaking, it is not allowed.
A pointer-to-something
is not compatible with a pointer-to-qualified-something
. Because a pointer-to-qualified-something
is not a qualified type of pointer-to-something
The same applies for
pointer-to-function-accepting-something
and
pointer-to-function-accepting-qualified-something
.
This can be found through C11 6.2.7 compatible type:
Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers...
Where 6.7.3 is the relevant part. It says
For two qualified types to be compatible, both shall have the identically qualified version of a compatible type;
The conversion chapter 6.3.2.3 does not contradict this:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
EDIT
As noted in the answer by Holt, the compatibility of two functions is explicitly described in 6.7.6.3/15.
I still think that a wrapper function is the best solution. The root of the problem is that write_a
isn't const-correct. If you can't change that function, then write a wrapper around it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With