2013-03-18 187 views
1

我有这样的C代码。在64位Linux系统上,结果是:4294967264而不是-32。 clang和gcc都会产生具有相同错误结果的二进制文件。 在该行的问题:va_arg 64位问题

*v = va_arg(args, long);
#include <stdio.h> 
#include <string.h> 
#include <stdarg.h> 

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; 
} 

回答

4

你确实需要一个long传递给你的函数。你通过了int

setter(&v, -32L); 
+0

谢谢,完全忘了这个。 – brovko 2013-03-18 16:03:39

3

在x86_64架构上,long的大小为64位。当你通过-32setter()时,它的类型是int,只有32位。如果您想要传递long,请明确投射它。例如:

setter((long *) &v, (long)-32); 
+0

-32L是一样的,没有演员。 – brovko 2013-03-18 16:09:57

1

小澄清:
如所述,在64位架构中,long是64位的。然而,这不是全部,因为C/C++会自动进行一些转换。在这里,setter()函数接受一个指定的参数和零个或多个未指定的参数。 -32参数是其中一个未指定的参数,因此编译器不知道实际上是否有long,并且保留了int(32位)。此外,还有一个额外的零被压入堆栈以保持64位对齐。这将产生如上所述的打印结果。因此,您必须在此明确指定您需要long-32L(long) -32)。但是如果函数实际上被声明为void setter (long *v, long arg),那么编译器会知道第二个参数是long,并自动转换为int参数。