Search code examples
cfunction-pointersimplicit-conversionvoid-pointers

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.


Solution

  • 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!