4

我有一个以标准方式使用可变参数的 c 函数,下面是一个简化示例:

    void func(parameter,...) {
     va_list args;
     va_start(args, parameter);

     //process args
     v1 = va_arg(args,sometype);
     v2 = va_arg(args,sometype);
        ...
     vn = va_arg(args,sometype);

     va_end(args);
}


//call func

func(parameter, p1, p2, ..., pn);

在所有 armv7s 及更低版本的设备以及包括 64 位模拟器在内的所有模拟器上,这都成功了,并且将 v1 到 vn 的变量分配给 p1 到 pn,但是当它在 arm64 上执行时,似乎可变参数列表是向后的( v1 = pn,v2 = pn-1, ..., vn = p1)

有什么解决办法吗?还是我错过了描述此更改的文档?

谢谢

编辑:

我没有提到这个问题的一个关键因素,我之前没有想到要提到。我试图用一个通用的可变参数函数来混合非可变参数函数。

注意:使用的编译器是 Apple LLVM 5.0

4

3 回答 3

2

我怀疑这与参数传递给函数的方式发生了变化有关。

有三种方法可以做到这一点:在寄存器中,在堆栈上以及两者的组合,这取决于参数的数量和类型。似乎 ARMv6、ARMv7 和 ARM64 架构在 ABI 所遵循的约定方面存在差异。

无论实际约定如何,编译器都应该透明地处理这个问题,因此如果工具链的行为不符合标准,您可能需要考虑更新工具链(您没有在问题中提及编译器,但这是关键)。

Apple关于跨不同架构版本的不同调用约定的文档可能有助于追踪编译器未考虑的任何更改。

有关 ARM 期望如何传递参数的更多信息,请参阅ARM 体系结构的过程调用标准的第 5.5 节(ARMv6、ARMv764 位版本的 ABI 中的第 5.4 节

于 2013-12-16T22:04:07.990 回答
1

首先,我想为没有在合理的时间内回复而道歉。在过去的一个月里,我一直低着头。

我在 Apple 论坛上发布了这个问题,似乎参数在可变参数函数中的打包方式与非可变参数函数打包参数的方式不同。

因此,虽然这在 armv7 和 armv7s 中有效,但您不能依赖它在 arm64 中工作,或者即使应用了高级别的优化。

我觉得如果这是真的,它有点违反 ABI,但我会接受它的本来面目。

于 2014-01-17T17:50:21.057 回答
0

仅当您在调用者和被调用者中使用相同类型时,可变参数才有效。例如,如果您传递 1 并尝试将其读取为 NSInteger,则在 64 位上失败,因为程序员不理解可变参数,而不是因为编译器错误。

我们还没有看到任何失败的代码。

于 2014-05-24T17:47:11.730 回答