gcc (x64) 如何处理可变函数中的 types/sizes?
How does gcc (x64) deal with types/sizes in variadic functions?
可变参数函数和 main()
#include <stdio.h>
#include <stdarg.h>
int f(long x,...)
{ va_list ap;
int i=0;
va_start(ap,x);
while(x)
{ i++;
printf("%ld ", x);
x=va_arg(ap,long);
}
va_end(ap);
printf("\n");
return i;
}
int main()
{ return f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,1L<<63,0);
}
在 gcc、linux 和 x64 上:即使 f() 的参数未转换为 64 位长,gcc 似乎也正确。
$ gcc t.c && ./a.out
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 -9223372036854775808
怎么办?
可变参数函数的参数是 "promoted" 到 linux x64 上的 64 位值,因此无需在此平台上显式转换为 64 位值。
使它工作的基本代码是
x = va_arg(ap, long);
改成其他类型,你可以搬起石头砸自己的脚。
char ch = va_arg(ap, char);
根据目标体系结构的规则,这可能会在每次访问后将 ap
递增 1、2、4 或 8。
可变参数函数和 main()
#include <stdio.h>
#include <stdarg.h>
int f(long x,...)
{ va_list ap;
int i=0;
va_start(ap,x);
while(x)
{ i++;
printf("%ld ", x);
x=va_arg(ap,long);
}
va_end(ap);
printf("\n");
return i;
}
int main()
{ return f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,1L<<63,0);
}
在 gcc、linux 和 x64 上:即使 f() 的参数未转换为 64 位长,gcc 似乎也正确。
$ gcc t.c && ./a.out
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 -9223372036854775808
怎么办?
可变参数函数的参数是 "promoted" 到 linux x64 上的 64 位值,因此无需在此平台上显式转换为 64 位值。
使它工作的基本代码是
x = va_arg(ap, long);
改成其他类型,你可以搬起石头砸自己的脚。
char ch = va_arg(ap, char);
根据目标体系结构的规则,这可能会在每次访问后将 ap
递增 1、2、4 或 8。