Visual Studio 2005 中的 x64 va_list

发布于 2024-08-02 05:05:55 字数 678 浏览 5 评论 0原文

我有一个类非静态成员函数,它有可变参数,我在 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不应该始终在堆栈上吗?

根据 大多数参考文献,我应该有一个干净的堆栈,其中充满了传递的内容参数。

我的问题是:这是正确的行为还是错误?如果这是一个错误,是我的错误还是微软的错误?

我定义了 WIN64 和 _M_AMD64,而 WIN32 未定义。

I have a class non-static member function, and it has variable arguments, I'm compiling on Visual Studio 2005, with the 64-bit runtime, on 64-bit Windows.

void Class::Foo(void* ptr,...)
{
    va_list args;
    va_start(args,ptr);
    float f=va_arg(args,float);
    va_end(args)
}

I'm expecting a float, I pass a float to the function. But when I debug - I don't get the float I've passed. In fact - it's being received by the function as a 64-bit double! I have to do this:

double d=va_arg(args,double);
float f=(float)d;

Now I know Win64 likes to pass parameters in registers, and casts floats when it does this, shouldn't a va_list always be on the stack?

According to most references, I should have just a clean stack full of the passed parameters.

My question is: is this correct behaviour, or a bug? And if it's a bug, is it my bug, or Microsoft's?

I have the defines WIN64 and _M_AMD64, and WIN32 is undefined.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

您的好友蓝忘机已上羡 2024-08-09 05:05:55

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

如果表达式表示
被调用函数的类型是
包括一个原型,参数是
隐式转换,就像通过
分配给类型
相应的参数,取
每个参数的类型为
其声明的不合格版本
类型。 a 中的省略号表示法
函数原型声明符原因
参数类型转换之后停止
最后声明的参数。这
默认参数促销是
对尾随参数执行。

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

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

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

I don't have the C++ standard here, but it follows the C standard in this matter. C99, 6.5.2.2p7 says

If the expression that denotes the
called function has a type that does
include a prototype, the arguments are
implicitly converted, as if by
assignment, to the types of the
corresponding parameters, taking the
type of each parameter to be the
unqualified version of its declared
type. The ellipsis notation in a
function prototype declarator causes
argument type conversion to stop after
the last declared parameter. The
default argument promotions are
performed on trailing arguments.

So for your float argument, "default argument promotions" are performed.
These are defined in p6 as

If the expression that denotes the
called function has a type that does
not include a prototype, the integer
promotions are performed on each
argument, and arguments that have type
float are promoted to double. These
are called the default argument
promotions. [...]

So all floats are converted to double when being passed to an ellipse. VS apparently conforms in this respect, and the bug is in your code, which shouldn't use float in va_arg.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文