天天看点

可变参数函数(一)

一个函数可以接受不定数的参数个数,这就是可变参数函数,比较常见的比如printf(),scanf();

printf(const char* format,…);
printf(“%d”,i);
printf(“%s”,s);
printf(“the number is %d,stirng is :%s”,i,s);      

变量参数函数的简单实现:

#include<stdio.h>
#include<stdarg.h>

int simple(int num,...)
{
    int i,result = 0;
    va_list vl;
    va_start(vl,num);
    printf("num:%d, vl:%d\n",num,*vl);
    for(i = 0; i < num - 1 ; i++)
    {
        result = va_arg(vl,int);
        printf("in for result:%d ,*vl:%d\n",result,*vl);
    }
    va_end(vl);
    return result;
}

int main()
{
    int sum = simple(5,1,2,3,4,5);
    if(0 == sum)
    {
        printf("simple failed\n");
    }
    else
    {
        printf("simple success! sum = %d\n",sum);    
    }
    return 0;
}      

结果如下:

exbot@ubuntu:~/wangqinghe/DeBug/20190702$ ./VA

num:5, vl:1020625376

in for result:1 ,*vl:1020625376

in for result:2 ,*vl:1020625376

in for result:3 ,*vl:1020625376

in for result:4 ,*vl:1020625376

simple success! sum = 4

sum.c
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>

double add(int n,...)
{
    //printf("add...\n");
    int i = 0;
    double sum = 0;
    va_list argptr;  
    va_start(argptr,n);  //初始化argptr
    for(i = 0 ; i < n; i++) ////对每个可选参数,读取类型为int的参数
    {
        sum += va_arg(argptr,int);        //累加到sum中
    }
    va_end(argptr);    
    printf("add_sum = %f\n",sum);
    return sum;
}

int main(int argc,char **argv)
{
    double sum = 0;
    int *p = malloc(argc * sizeof(int));
    int i;
    for(i = 1; i < argc; i++)        
    {        
        p[i] = atoi(argv[i]);    
        printf("p[%d] = %d\n",i,p[i]);
    }

    sum = add(argc,p[1]);
    printf("sum = %f\n",sum);
    sum = add(argc,p[1],p[2]);
    printf("sum = %f\n",sum);
    sum = add(argc,p[1],p[2],p[3]);
    printf("sum = %f\n",sum);        

    free(p);
    return 0;
}      

输出结果;

exbot@ubuntu:~/wangqinghe/DeBug/20190702$ ./sum 10 20 30

p[1] = 10

p[2] = 20

p[3] = 30

add_sum = 239745405.000000

sum = 239745405.000000

add_sum = 56.000000

sum = 56.000000

add_sum = 69.000000

sum = 69.000000

相关函数介绍:

可变函数列表的实现由几个宏组成的,在文件#include<stdarg.h>中。

va_list 定义某个变量,内核的定义如下:

typedef char *va_list;  //字符指针类型

#ifndef __sparc__
#define va_start(AP, LASTARG)                         \
 (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))//ap指向下一个参数,lastarg不变
#else
#define va_start(AP, LASTARG)                         \
 (__builtin_saveregs (),                        \
  AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) //跳过下第一个参数,指向第二个参数内存地址
#endif

//对type向上取整 取int的整 4,然后乘上int整型4的倍数
#define __va_rounded_size(TYPE)  \
  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))      
//  first=va_arg(args,int)
#define va_arg(AP, TYPE)                        \//ap指向下一个类型的参数
 (AP += __va_rounded_size (TYPE),                    \//返回ap - sizeof(type)参数,即前一个参数
  *((TYPE *) (AP - __va_rounded_size (TYPE))))

//对type向上取整 取int的整 4,然后乘上int整型4的倍数
#define __va_rounded_size(TYPE)  \
  (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))