在C++中,可变参数函数(在参数列表末尾带有...的函数)必须遵循__cdecl调用约定吗?

Ben*_*Ben 7 c++ cdecl variadic-functions stdcall

我知道__stdcall函数不能有省略号,但我想确保没有支持stdarg.h函数的平台来调用除__cdecl或__stdcall之外的约定.

Jer*_*fin 8

调用约定必须是调用者从堆栈中清除参数的约束(因为被调用者不知道将传递什么).

但这并不一定与微软称之为"__cdecl"的内容相对应.例如,在SPARC上,它通常会传递寄存器中的参数,因为这就是SPARC设计工作的方式 - 它的寄存器基本上充当调用堆栈,如果调用足够深,则会溢出到主存储器他们将不再适合登记.

虽然我不太确定它,但我希望在IA64(Itanium)上大致相同 - 它也有一个巨大的寄存器集(如果内存服务,则会有几百个).如果我没有弄错的话,它对你如何使用寄存器更加宽容,但我希望它至少在很多时候都能被类似地使用.

为什么这对你很重要?使用stdarg.h及其宏的目的是隐藏调用约定与代码之间的差异,因此它可以移植地使用变量参数.

编辑,基于评论:好的,现在我明白你在做什么(至少足以改善答案).鉴于您已经(显然)拥有处理默认ABI变体的代码,事情就更简单了.这只留下了可变函数是否总是使用"默认ABI"的问题,无论发生在手头的平台上是什么.以"stdcall"和"default"为唯一选项,我认为答案是肯定的.只是举例,在Windows上,wsprintfwprintf打破经验法则,并使用cdecl调用约定,而不是STDCALL.

  • *"为什么这对你很重要?"*Ben正在为Mozilla开发js-ctypes.您可以在https://bugzilla.mozilla.org/show_bug.cgi?id=554790(搜索"疯狂的想法")中查看确切的上下文,您可以在https://developer.mozilla上解释js-ctypes的一些文档.组织/ EN/JavaScript_code_modules/ctypes.jsm (2认同)