我想知道将double (*)(double)
转换为double(*)(...)
是否安全,这将用于概括可能包含多个函数指针的代码。
到目前为止,我已经存储了将要传递给向量中的函数的所有内容,并且我想知道是否有一种方法可以调用函数(同时传递正确数量的参数)码?我的意思是:
//while initializing
mFunction = sin;
//later in code
double (*generalized)(...) = mFunction;
for(i=0;i<args.size();i++)
pusharg(args[i]);
call(generalized);
- 编辑 -
如果使用c ++没有有效的方法,可以使用汇编来轻松调用该函数吗?
答案 0 :(得分:3)
您无法直接将double(*)(double)
分配给double(*)(...)
,但可以reinterpret_cast
。 §5.2.10[expr.reinterpret.cast] / 6明确允许转换,但调用转换函数指针将导致未定义的行为:
函数指针可以显式转换为不同类型的函数指针。
通过指向与函数定义中使用的类型不同的函数类型的指针调用函数的效果是 undefined 。
将“指向
T1
”的类型的prvalue转换为“指向T2
”的类型(其中T1
和T2
为函数类型)并返回对于其原始类型产生原始指针值,未指定此类指针转换的结果。
很容易理解为什么它会导致UB - 如果我们打电话给generalized(1.0, 2.0, 3.0)
怎么办?这可能会破坏调用堆栈。但是如果你在调用它之前将generalized
强制转换回double(*)(double)
,那就没关系了。
答案 1 :(得分:1)
是的,铸造本身是允许的。但是,用错误的签名来调用它并不是。注意,如果你想要一个泛型函数指针,最好使用void (*)()
,它就像void*
一样用于函数指针(尽管没有隐式转换)。
甚至更好,因为你通常提供特定的参数,使用std::function
和std::bind
(如果您的编译器支持C ++ 11库)或它们的Boost等价物。
答案 2 :(得分:0)
使generalized
volatile需要编译器遵循ABI规范。由于需要支持非声明的C函数,如果没有调用除了可变数量的参数之外的函数,这对于具有固定数量的参数的函数来说,这对于大多数ABI(包括x86和x86-32)是安全的。