stdcall 可以有可变参数吗?

发布于 2024-09-17 15:39:47 字数 330 浏览 12 评论 0原文

据我所知,只有 caller-clean-stack 约定可以使用变量参数。
顺便说一句,WinApi StringCchPrintfW 是这样声明的。(我删除了 SAL)

__inline HRESULT __stdcall
StringCchPrintfW(
STRSAFE_LPWSTR pszDest、size_t cchDest、STRSAFE_LPCWSTR pszFormat、...
);

stdcall 也可以有可变参数吗?

As far as I know, only the caller-clean-stack convention can use variable arguments.
By the way, the WinApi StringCchPrintfW is declared like this.(I removed the SAL)

__inline HRESULT __stdcall
StringCchPrintfW(
STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, ...
);

Can stdcall have a variable arguments either?

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

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

发布评论

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

评论(1

泪眸﹌ 2024-09-24 15:40:37

不可以。stdcall 调用约定具有被调用者清理堆栈。由于被调用者正在清理堆栈,因此它无法在编译时知道要弹出多少内容,因此它不能具有可变参数。

为了拥有可变数量的函数参数,您需要使用 cdecl ,让调用者清理堆栈。这一切都由编译器确定传递了多少参数,并且由于调用者正在清理堆栈,因此它也知道当函数调用返回时从堆栈中弹出多少参数。

在上述情况下,函数被声明为使用 __stdcall,正如前面提到的,它不支持变量参数。在这种情况下,编译器决定忽略定义的调用约定并恢复到 __cdeclstdcall,上面提到的。我引用:

被调用者清理堆栈,因此
编译器生成 vararg 函数
__cdecl

如果编译以下代码并反汇编对该函数的调用,则可以观察到这一点。

int __stdcall Bar(int a, int b, ...)
{
  return b * a;
}

生成的代码将被视为__cdecl。至于这样定义的原因,我不知道。

No. The stdcall calling convention has the callee clean the stack. Since the callee is cleaning the stack there is no way for it to know at compile time how much to pop off, therefore it cannot have variable arguments.

In order to have variable number of function arguments you need to use cdecl, which has the caller clean the stack. This all the compiler to determine how many arguments are being passed and since the caller is cleaning up the stack it also knows how much to pop off the stack when the call to the function returns.

In the case mentioned above, the function is declared to use __stdcall, which as previously mentioned does not support variable arguments. In this case, the compiler makes the decision to ignore the calling convention defined and revert back to __cdecl. This behavior is alluded to in the description for stdcall, mentioned above. I quote:

The callee cleans the stack, so the
compiler makes vararg functions
__cdecl.

This can be observed if the following code is compiled and a call to the function disassembled.

int __stdcall Bar(int a, int b, ...)
{
  return b * a;
}

The resulting code will be treated as __cdecl. As to the reason this is defined that way, I do not know.

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