可變參數函數(一)


一個函數可以接受不定數的參數個數,這就是可變參數函數,比較常見的比如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;  //字符指針類型

va_start(ap,type) 開始獲取可變參數列表中第一個參數(…里面的第一個),也就是跳過第一個參數。(所以以上的第一個輸出是個隨機值)。

#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))

Va_arg(args,int)循環獲取可變參數列表中的參數,args指向下一個參數地址,返回的是當前參數地址。

//  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))

最后一個va_end(ap)結束標志,在程序中只是作為一個可變參數列表的結束標識,在stdarg.h中僅僅定義了一下,沒有實現代碼部分。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM