在C中转换这些函数指针是否安全?

时间:2015-01-27 17:00:57

标签: c casting type-conversion function-pointers void-pointers

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

2 个答案:

答案 0 :(得分:1)

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

我在我的运算符构造函数中完成了这个here,该函数将各种函数类型存储在" generic" form,但它们在运算符执行函数中转换为正确的类型。这似乎适用于Cygwin / mingw / Ubuntu中的gcc,带solaris的suncc和Visual Studio。我在这里的替代方案是非原型函数指针,它给了我大量的噪声编译器警告。


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

答案 1 :(得分:0)

我猜你回答了自己的问题:不,这不安全。如果你正在构建voidarg(来自和来自),你实际上是在向编译器说你知道你在做什么。

这是编译器为您提供的灵活性,但您必须为负责正确的投射付出代价。