可变长参数---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);



posted @ 2020-03-02 15:53  ren_zhg1992  阅读(178)  评论(0)    收藏  举报