Home > Software design >  Generic function typedef in C - how to get rid of initialization warning?
Generic function typedef in C - how to get rid of initialization warning?

Time:02-20

I'm experimenting with generic-like code and I have a function like this (a lot of not relevant code removed):

typedef uint8_t (*struct_converter_t)(void *, char *);

void convert_struct(
        struct_converter_t converter, // this is a function
        const char * file_name
){
    some_struct_t * some_struct;
    converter(some_struct, some_string_buffer);
}

I'm getting this:

initialization of 'struct_converter_t' {aka 'unsigned char (*)(void *, char *)'} from incompatible pointer type 'uint8_t (*)(some_struct_t *, char *)' {aka 'unsigned char (*)(struct <anonymous> *, char *)'} [-Wincompatible-pointer-types]

EDIT:

For those who ask about line number. Not simplified code looks like this:

enter image description here

I'm not experienced in C and I would like to know if there is a way to get rid of this warning elegantly.

CodePudding user response:

The function that you're assigning to the function pointer type has parameters that are incompatible with the function pointer.

Your function takes a some_struct_t * as the first parameter but the function pointer type takes a void * as the first parameter. While any object pointer can be converted to/from a void *, that does not extend to function pointer parameters.

You need to change your function to take a void * for its first parameter to be compatible with the function pointer. Then inside the function you can convert that void * parameter to a some_struct_t *.

CodePudding user response:

In C, you can supply an argument of type X* to a function expecting a void*. But that's as far as the conversion goes. You cannot take a function whose first parameter is an X* and use it as the argument for a parameter which is a function whose first parameter is a void*.

The reason is that C does not guarantee that X* and void* have the same representation. It does guarantee that the compiler knows how to convert an X* into a void* in a way that does not destroy information, so that it can be later converted back to an X*. But the void* might look quite different.

So the compiler can insert code which changes the X* to a void*. But how does it change a char*(*)(X*) (a function whose parameter is an X*) to a char*(*)(void*)? If the function is expecting that arg has type char*(*)(void*), then it will mostly likely call arg(v)wherevhas typevoid*. What then happens if argactually expects anX*`?

In order for the compiler to allow that possibility, it would have to somehow wrap arg in what's usually called a trampoline; a function which accepts an X* and converts it into a void* in order to call a different function. That's not so easy -- for one thing, it would have to store the trampoline somewhere -- so C refuses to do it as an automatic conversion.

  • Related