我有一个以标准方式使用varadic参数的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
答案 0 :(得分:2)
我怀疑这与改变参数传递给函数的方式有关。
有三种方法可以做到这一点:在寄存器中,在堆栈上和两者的组合取决于参数的数量和类型。似乎ARMv6,ARMv7和ARM64架构在ABI遵循的惯例方面存在差异。
无论实际约定如何,编译器都应该透明地处理它,因此如果它不符合标准,你可能不得不考虑更新你的工具链(你的问题中没有提到编译器,但这是关键) )。
关于不同体系结构版本的不同调用约定的Apple's documentation可能有助于跟踪编译器未考虑的任何更改。
有关ARM如何传递参数的更多信息,请参阅Procedure Call Standard for the ARM architecture(ARMv6, ARMv7的第5.5节和section 5.4 in the 64 bit version of the ABI
答案 1 :(得分:2)
首先,我要为在合理的时间内没有回应而道歉。在过去的一个月里,我一直低调。
我在Apple论坛上发布了这个问题,似乎参数在可变参数函数中的打包方式与非变量函数打包参数的方式不同。
因此,虽然这在armv7和armv7s中有效,但您不能依赖它在arm64中工作,即使应用了高级别的优化。
我觉得如果这是真的,那就违反了ABI,但我会把它当作它。
答案 2 :(得分:0)
只有在调用者和被调用者中使用相同类型时,Varargs才有效。例如,如果您传递1并尝试将其作为NSInteger读取,那么64位失败是因为程序员不理解varargs,而不是因为编译器错误。
我们仍然没有看到任何代码失败。