我有一个类非静态成员函数,它有可变参数,我在64位Windows上使用64位运行时在Visual Studio 2005上进行编译。
void Class::Foo(void* ptr,...)
{
va_list args;
va_start(args,ptr);
float f=va_arg(args,float);
va_end(args)
}
我期待浮动,我将浮动传递给函数。但是当我调试时 - 我没有得到我已经通过的浮动。事实上 - 它被64位双功能接收!我必须这样做:
double d=va_arg(args,double);
float f=(float)d;
现在我知道Win64喜欢在寄存器中传递参数,并在执行此操作时强制转换浮点数,va_list是否总是在堆栈中?
根据most references,我应该只有一个包含传递参数的干净堆栈。
我的问题是:这是正确的行为还是错误?如果它是一个错误,它是我的错误,还是微软的?
我有定义WIN64和_M_AMD64,WIN32未定义。
答案 0 :(得分:1)
我这里没有C ++标准,但它在这个问题上遵循C标准。 C99,6.5.2.2p7说
如果表达式表示 被调用的函数有一个类型 包括原型,参数是 隐式转换,好像是 赋值,类型 相应的参数,取 每个参数的类型 其声明的不合格版本 类型。省略号中的省略符号 函数原型声明器的原因 参数类型转换后停止 最后声明的参数。该 默认参数促销是 在尾随参数上执行。
因此,对于您的float参数,将执行“默认参数提升”。 这些在p6中定义为
如果表达式表示 被调用的函数有一个类型 不包括原型,整数 每个都进行促销活动 参数和具有类型的参数 浮动升级为双倍。这些 被称为默认参数 促销活动。 [...]
因此,当传递给椭圆时,所有浮点数都会转换为double。 VS在这方面显然符合,并且错误在您的代码中,不应在float
中使用va_arg
。
答案 1 :(得分:1)