Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get incompatible-pointer-types warning except void *

#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.

like image 595
toyvenu Avatar asked Nov 22 '25 19:11

toyvenu


2 Answers

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!

like image 87
Lundin Avatar answered Nov 24 '25 10:11

Lundin


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.

like image 40
Adrian Mole Avatar answered Nov 24 '25 10:11

Adrian Mole



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!