1
votes

I have the following code:

#include <stdlib.h>
#include <stdio.h>

typedef void (*func_t)(void * data);

void func2(int * arg, func_t free_func) {
        free_func(arg);
}

void func(int * a) {
        printf("%d\n", *a);
}

int main(int argc, char ** argv) {
        int a = 4;
        func2(&a, func);
        return 0;
}

Compiling which gives me warning: passing arg 2 of `func2' from incompatible pointer type

Why is that? Shouldn't int pointer be compatible with void pointer?

4

4 Answers

3
votes

That you can cast the types doesn't mean the compiler will happily do so for you.

In this case the function pointer definition doesn't match up. C is not going to assume that a function declared to take int* will be happy instead with a void*, even though the conversion between those two types is implicit. This is a subtle gotcha in how C handles function pointers.

If you want this to work without warnings, you will have to cast like so:

func2(%a, (func_t)func);
1
votes

You can also do this:

free_func((int *)arg);

Note though that converting a void * to T* (in this case int*) is unsafe due to the side-effects of using a T* that is not actually pointing to a T

e.g.

char i = 0;
char j = 0;    
char* p = &i;
void* q = p;
int* pp = q;    /* unsafe, legal C, not C++ */
printf("%d %d\n",i,j);
*pp = -1;   /* overwrite memory starting at &i */
 printf("%d %d\n",i,j);
1
votes

Pointer types are compatible only if their base types are compatible, and int and void are not compatible.

Furthermore, it is possible for int and void pointers to have different sizes and representations.

0
votes

If you change the declaration / definition of func to

void func(void * a) {
        printf("%d\n", *(int*)a);
}

everything works as you'd expect.