#include <stdio.h>
void fun1(int *c){return;}
void fun2(void *p){return;}
void fun3(void **p){return;}
typedef void (* myfunptr)(void *);
void fun4(myfunptr b){
return;
}
int
main(){
int *p;
void *q = p;
fun1(p); //no warning
fun1(q); //no warning
fun2(p); //no warning
fun2(q); //no warning
fun3(&p); //warning - incompatible pointer types
fun3(&q); //no warning
fun4(fun1); //warning - incompatible pointer types
fun4(fun2); //no warning
return 0;
}
I am realizing warning at fun3(&p) as void ** is not a generic pointer like void *. However, I'm a little puzzled why there is a warning in the case of fun4(fun1), as void * and int * are implicitly converted without warning.
My next question is there a way I will get warnings of "incompatible types" for all non-compatible pointer conversion except when void * or void ** involved. Because using -Wno-incompatible-pointer-types disables warnings of all types of conversions.
fun1(p); //no warning
int* is obviously compatible with int*
fun1(q); //no warning
void*, as a special case type, is compatible with every other object pointer type and are implicitly converted to/from other pointers to object type.
fun2(p); //no warning
As already mentioned, void* and int* can be implicitly converted to/from each other.
fun2(q); //no warning
void* is obviously compatible with void*
fun3(&p); //warning - incompatible pointer types
The special rule for void* does not apply "recursively". void** is not a generic object pointer type. It is not compatible with int**. You'll see some trashy APIs doing such conversions still (CUDA etc), but they are bad and relying on non-standard behavior.
fun3(&q); //no warning
void** is obviously compatible with void**.
fun4(fun1); //warning - incompatible pointer types
Function pointers need to point at identical functions to be compatible. Same return type, same parameters, same qualifiers.
fun4(fun2); //no warning
You provide a function pointer of the expected type, so it is fine. Please note that fun2 in this case "decays" from a function to a function pointer, since it is used in an expression.
Also please note that void* is the generic object pointer. You cannot use it as a generic pointer type to mix with function pointers!
Although int* is implicitly convertible to void* (as you say, without warning), the case for your fun4(fun1); statement is rather different. In that case, you are implicitly converting a function pointer – between pointers to functions with different signatures.
A fuller discussion of compatibility between pointers to different types of function can be found here: Casting a function pointer to another type.
Although, in your particular case, there should be no issues when calling fun1 through the fun4 pointer parameter (because, as you say, the former has an argument list compatible with that provided for the fun4 parameter), the compiler is still (IMHO) 'justified' in providing you with a warning that the signature for fun1 is different from that for the expected myfunptr.
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