Visual Studio 2005中的x64 va_list

时间:2009-08-13 11:43:45

标签: visual-studio stack 64-bit win64 variadic-functions

我有一个类非静态成员函数,它有可变参数,我在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未定义。

2 个答案:

答案 0 :(得分:1)

我这里没有C ++标准,但它在这个问题上遵循C标准。 C99,6.5.2.2p7说

  

如果表达式表示   被调用的函数有一个类型   包括原型,参数是   隐式转换,好像是   赋值,类型   相应的参数,取   每个参数的类型   其声明的不合格版本   类型。省略号中的省略符号   函数原型声明器的原因   参数类型转换后停止   最后声明的参数。该   默认参数促销是   在尾随参数上执行。

因此,对于您的float参数,将执行“默认参数提升”。 这些在p6中定义为

  

如果表达式表示   被调用的函数有一个类型   不包括原型,整数   每个都进行促销活动   参数和具有类型的参数   浮动升级为双倍。这些   被称为默认参数   促销活动。 [...]

因此,当传递给椭圆时,所有浮点数都会转换为double。 VS在这方面显然符合,并且错误在您的代码中,不应在float中使用va_arg

答案 1 :(得分:1)