我想调用一个 extern "C"
函数,例如f1(int a, float f, double d, void* ptr)
使用带有实际参数的前向声明,但在实际实现中我想使用 va_list
和 friend pop
参数。让我们想象一下,我有一个有效的用例,它被允许吗?
main.cpp
extern "C" void f(int anchor, int a, float f, double d, void* ptr, char c);
int main(int, char*)
{
f(0, 42, 1.08f, 3.14, reinterpret_cast<void*>(0xcafebabe), 'c');
return 0;
}
impl.cpp
#include <cstdarg>
#include <iostream>
#include <iomanip>
using namespace std;
void f(int anchor, ...)
{
va_list args;
va_start(args, anchor);
int a = va_arg(args, int);
float f = va_arg(args, float);
double d = va_arg(args, double);
void* ptr = va_arg(args, void*);
char c = va_arg(args, char);
cout << a << ' '
<< f << ' '
<< d << ' '
<< hex << (std::ptrdiff_t)ptr << ' '
<< (int)c << endl;
va_end(args);
}
代码至少在 MSVC 2015 上运行并打印正确的值,现在的问题是:它是否保证可以工作,如果不能:它是否可能在最重要的平台和编译器上工作?
最佳答案
从理论上讲,您的代码会受到未定义行为的影响。事实上,当我尝试在使用 g++ 构建后运行该程序时,我得到了
Illegal instruction (core dumped)
原因是当一个函数有可变参数时,它能处理的只有int
、double
、指针。它无法处理 float
和 char
。
如果声明被指定为:
extern "C" void f(int anchor, ...);
float
将被提升为 double
而 char
将被提升为 int
。
在实现方面,您需要使用:
float f = (float)va_arg(args, double);
和
char c = (char)va_arg(args, int);
参见 Default argument promotions in C function calls有关该主题的更多信息。
关于c++ - 函数参数中的省略号是否使用与普通参数相同的调用布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33696478/