有没有办法从varargs函数的参数中检索浮点数?

如果函数是用原型定义的,该原型明确说明了参数的类型,例如。

void somefunc(int arg1, float arg2); 

但实施为

 void somefunc(int arg1, ...) { ... } 

是否可以使用va_arg来检索浮点数? 它通常被禁止这样做,因为varargs函数具有隐式类型提升,例如float to double,因此尝试检索未启动类型是不受支持的,即使使用未启动类型调用函数对更具体的函数原型也是如此。

这样做的原因是在运行时检索不同类型的参数,作为obj-c解释器的一部分,其中一个函数将被重用于所有不同类型的方法。

这最好是独立于架构(因此,如果没有其他相同的代码在模拟器和设备上工作),尽管如果没有办法这样做,那么将接受设备特定的修复。

编辑:忘了特别提到:函数知道参数的类型和数量(它查找要使用SEL _cmd参数进行地图查找解释的代码)

您可以执行以下操作:

 static inline uint32_t floatparam (float f) { union { uint32_t u; float f; } u; uf = f; return uu; } 

然后总是这样调用你的函数:

 fn(5, floatparam(0.5f), floatparam(1.1f), ...); 

在你的function中,你会这样做

 va_list val; va_start (val, arg1); while () { union { float f; uint32_t u; } u; uu = va_arg (val, uint32_t); // float is now in uf } 

这避免了不必要的类型促销问题,并且不需要汇编语言。

当然,你不应该误导你的function。 如果它是一个varargs函数,它是一个varargs函数,句点。 正如bbum所说,ABI是不同的。

您几乎必须使用每个体系结构的程序集才能执行此操作。 首先,你不能使用varargs,因为 – 正如你暗示的那样 – varargs的调用ABI与非varargs的调用ABI不同; 参数编码方式不同,寄存器状态在调用边界上不同。

最简单的方法是创建大量的存根函数,以及您需要的所有论证变体。 然后,每个存根都会将特定的参数和包捆绑到一些更通用的内容中,以便代码更普遍地使用。

如果你不想走那条路,那么你将不得不知道参数的类型,特定目标ABI的参数的编码规则,然后你需要编写代码来有效地撕掉当您的通用蹦床被调用时,他们的隐藏洞中的争论。

并且你需要做所有这些,同时也不要通过无意的寄存器使用来破坏任何参数。 您可能会发现我对objc_msgSend()的描述间接有用,因为它描述了Objective-C如何处理这个问题(提示:它不遗余力地触及前两个之外的任何参数)。

如果在显示时声明并定义了函数,则无法执行任何操作,尤其是在与体系结构无关的方式中。 代码被破坏了。 它不起作用。 在C中的可变函数和非可变函数之间绝对没有兼容性。这些函数具有完全不同的性质,它们属于两个完全不同的非交叉世界。

如果在您的特定实现/体系结构中,这两个可能以某种方式被迫一起工作,这是您的实现的具体细节。 在这种情况下,您必须研究您的特定架构。

您总是可以放弃varargs,而是将所有参数编码为字符串。 您的function界面保持不变,您可以完全自由地解释所需的数据。 然而,这不是一个漂亮的解决方案,因为你实际上是在实现一个脚本解析器。