C 中的通用函数 typedef - 如何摆脱初始化警告?

Generic function typedef in C - how to get rid of initialization warning?

我正在试验类似通用的代码,我有一个这样的函数(删除了很​​多不相关的代码):

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);
}

当我尝试分配一个接受 some_struct_t(而不是 void *)的函数时:

static uint8_t some_converter(some_struct_t * vd, char * s);

给我的 struct_converter_t 像这样:

struct_converter_t converter = some_converter;    // WARNING HERE

我明白了:

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]

我对 C 没有经验,我想知道是否有办法优雅地摆脱这个警告。

您分配给函数指针类型的函数具有与函数指针不兼容的参数。

您的函数将 some_struct_t * 作为第一个参数,但函数指针类型将 void * 作为第一个参数。虽然任何对象指针都可以 to/from 转换为 void *,但不会扩展到函数指针参数。

您需要更改您的函数,使其第一个参数采用 void * 以与函数指针兼容。然后在函数内部,您可以将 void * 参数转换为 some_struct_t *.

在 C 中,您可以向需要 void* 的函数提供类型 X* 的参数。但就转换而言,仅此而已。您不能将第一个参数为 X* 的函数用作第一个参数为 void*.

的函数的参数

原因是C不保证X*void*表示相同。它确实保证编译器知道如何以不破坏信息的方式将 X* 转换为 void*,以便稍后可以将其转换回 X*。但是 void* 可能看起来很不一样。

因此编译器可以插入将 X* 更改为 void* 的代码。但是它如何将 char*(*)(X*)(参数为 X* 的函数)更改为 char*(*)(void*)?如果函数期望 arg 的类型为 char*(*)(void*),那么它很可能会调用 arg(v),其中 v 的类型为 void*。如果 arg 实际上期望 X* 会发生什么?

为了让编译器允许这种可能性,它必须以某种方式将 arg 包装在通常称为蹦床的东西中;一个接受 X* 并将其转换为 void* 以调用不同函数的函数。这不是那么容易——一方面,它必须将蹦床存储在某个地方——所以 C 拒绝将其作为自动转换。