在voidarg
和chararg
之间或voidarg
和fooarg
之间进行转换是否安全?:
typedef int (*voidarg)(void *);
typedef int (*chararg)(char *);
typedef int (*fooarg)(foo_t *);
或voidret
与charret
之间或voidret
与fooret
之间?:
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);
}
答案 0 :(得分:1)
如果在调用之前将指针强制转换为正确的类型,我希望转换是安全的。这也假设它们都使用相同的调用约定装饰声明。
我在我的运算符构造函数中完成了这个here,该函数将各种函数类型存储在" generic" form,但它们在运算符执行函数中转换为正确的类型。这似乎适用于Cygwin / mingw / Ubuntu中的gcc,带solaris的suncc和Visual Studio。我在这里的替代方案是非原型函数指针,它给了我大量的噪声编译器警告。
对于更新,不,至少从便携性的角度来看,这对我来说并不安全。通过错误类型的指针调用该函数是未定义的行为。 void *
类型能够存储指向任何对象类型的指针(不一定是函数,但这不是问题)。并且函数指针能够存储不同签名的函数指针,但是通过错误类型调用可能实现类似于" reinterpret_cast"或者它可能会爆炸。
答案 1 :(得分:0)
我猜你回答了自己的问题:不,这不安全。如果你正在构建voidarg(来自和来自),你实际上是在向编译器说你知道你在做什么。
这是编译器为您提供的灵活性,但您必须为负责正确的投射付出代价。