可变长参数---va_list
一般格式:
void fun(int x, ...)
参数x后面为可变参数区。
下面举个栗子,学习一下可变参数的使用,顺便提一下典型的32位程序在64位下的错误。
可变参数,会从参数x,后将可变参数列表放入到arglist中,
然后用va_arg去列表里面取,后面类型就是取出来之后转换成的类型。
实例:
void fun(int x, ...)
{
va_list arglist;
va_start(arglist, x);
char *p = (char*)va_arg(arglist, int);
printf("%p\n", p);
printf("%c\n", *p);
int n = va_arg(arglist, int);
printf("%d\n", n);
}
int main()
{
char c = 'c';
int n = 10;
printf("%p\n", &c);
fun(1, &c, n); // 64位下运行时,报段错误!!
const char *p = "cc"; // 运行时不会报错,因为这里分配地址还没超过4字节
printf("%p\n", p);
fun(2, p, n);
return 0;
}
在64位下编译运行:
# g++ -Wall -Wconversion -Wsign-compare -m64 arglist.cpp -o arglist
# ./arglist
0x7ffd31f6423f
0x31f6423f
Segmentation fault
修改后:
char *p = (char*)va_arg(arglist, uintptr_t);
# g++ -Wall -Wconversion -Wsign-compare -m64 arglist.cpp -o arglist
# ./arglist
0x7ffea5e2d06f
0x7ffea5e2d06f
c
10
0x400820
0x400820
c
10
至于为什么下面这两种方式中,由于分配的地址没有超过4字节,运行时不会报错,暂不清楚,但是为了更安全,64位下表示地址还是用uintptr_t
const char *p = "cc";
fun(2, p, n);
或者直接传
fun(2, “@xxxx”, n);

浙公网安备 33010602011771号