va_arg 64位问题
我有这样的C代码。 在64位Linux系统上,结果是:4294967264而不是-32。 clang和gcc都生成具有相同错误结果的二进制文件。 行中的问题:
* v = va_arg(args,long);
#include #include #include void setter(long *v, ...) { va_list args; va_start(args, v); *v = va_arg(args, long); va_end(args); } int main() { long v = 0; setter((long *) &v, -32); printf("%ld\n", v); return 0; }
你实际上需要传递一个long
的function。 你正在传递一个int
。
setter(&v, -32L);
在x86_64架构上, long
的大小为64位。 当您将-32
传递给setter()
,其类型为int
且仅为32位。 如果你想要传递long
,请明确地转换它。 例如:
setter((long *) &v, (long)-32);
一点澄清:
如上所述,在64位体系结构中, long
为64位。 然而,这不是整个故事,因为C / C ++会进行一些自动转换。 这里, setter()
函数接受一个指定的参数和零个或多个未指定的参数。 -32参数是那些未指定的参数之一,因此编译器不知道实际上是long
并且保留int
(32位)。 此外,将额外的零推入堆栈以保持64位对齐。 这将产生如上所述的打印结果。 因此,您必须在此处明确指定您需要一个long
( -32L
或(long) -32
)。 但是如果函数实际上已经声明为void setter (long *v, long arg)
,那么编译器就会知道第二个参数是long
,并自动转换int
参数。