在 C 中的这些函数指针之间进行转换是否安全?

Is it safe to convert between these function pointers in C?

voidargchararg之间或voidargfooarg之间转换是否安全?:

typedef int (*voidarg)(void *);
typedef int (*chararg)(char *);
typedef int (*fooarg)(foo_t *);

或介于 voidretcharret 之间或介于 voidretfooret 之间?:

typedef void *(*voidret)(int);
typedef char *(*charret)(int);
typedef foo_t *(*fooret)(int);

我知道这在 C++ 中可能不安全(特别是对于未知的 foo_t 类型),但根据任何 C 标准或主要 C 编译器,它是否安全?

编辑:

我忘了提一个重点。我也想调用这些函数,即能够做到这一点:

int charfunc(char *s) { /* ... */ }
char str[] = "...";

int somefunction(voidarg f, void *data)
{
    return f(data);
}

int main()
{
    int i = somefunction(charfunc, str);
}

我想您已经回答了您自己的问题:不,这不安全。如果你正在转换 voidarg(从和到)你实际上是在告诉编译器你知道你在做什么。

这是编译器给你的灵活性,但你必须为正确的转换付出代价。

我希望转换是安全的,前提是指针在调用之前被转换为正确的类型。这还假设它们都使用相同的调用约定装饰声明。

我在我的运算符构造函数中完成了此操作 here,该函数以 "generic" 形式存储各种函数类型,但它们在运算符执行函数中被强制转换为正确的类型。这似乎适用于 Cygwin/mingw/Ubuntu 中的 gcc、适用于 solaris 的 suncc 和 Visual Studio。我的替代方案是非原型函数指针,它给了我大量嘈杂的编译器警告。


对于更新, 不,至少从可移植性的角度来看,这对我来说并不安全。通过错误类型的指针调用函数是未定义的行为。 void * 类型能够存储指向任何对象类型的指针(不一定是函数,但这不是这里的问题)。并且函数指针能够存储不同签名的函数指针,但是通过错误的类型调用 可能 实现类似 "reinterpret_cast" 的东西,否则它可能会崩溃。