函數樣例:
#include<stdio.h> #include<stdlib.h> #include<stdarg.h>double add(int n,...) {int i = 0;double sum = 0;va_list argptr;va_start(argptr,n);for(i = 0 ; i < n; i++){double d = va_arg(argptr,double);printf("%d argument is %.3f\n",i,d); //獲取第i個double型的可變參數sum += va_arg(argptr,double); }va_end(argptr); return sum; }int main(int argc,char **argv) {double sum = 0;float *p = malloc(argc * sizeof(float));int i;for(i = 1; i < argc; i++) { p[i] = atof(argv[i]); //printf("p[%d] = %.3f\n",i,p[i]); }sum = add(1,p[1]); printf("sum = %.3f\n",sum);sum = add(2,p[1],p[2]); printf("sum = %.3f\n",sum);sum = add(3,p[1],p[2],p[3]); printf("sum = %.3f\n",sum);free(p);return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/DeBug/20190702$ gcc sum.c -o sum
exbot@ubuntu:~/wangqinghe/DeBug/20190702$ ./sum 10 20 30
0 argument is 10.000
sum = 0.000
0 argument is 10.000
1 argument is 0.000
sum = 20.000
0 argument is 10.000
1 argument is 30.000
2 argument is 0.000
sum = 20.000
?
測試:double d =? va_arg(argptr,double);是否只提取可變參數列表中double類型的數據
#include<stdio.h> #include<stdlib.h> #include<stdarg.h>double add(int n,...) {int i = 0;double sum = 0;va_list argptr;va_start(argptr,n);for(i = 0 ; i < n; i++){double d = va_arg(argptr,double);printf("%d argument is %.3f\n",i,d);sum += va_arg(argptr,double); }va_end(argptr); return sum; }int main(int argc,char **argv) {double sum = 0;float *p = malloc(argc * sizeof(float));int i;for(i = 1; i < argc; i++) { if(0 == i % 2) {p[i] = atof(argv[i]);printf("float : p[%d] = %.3f\n",i,p[i]); }}sum = add(1,p[1]); printf("sum = %.3f\n",sum);sum = add(2,p[1],p[2]); printf("sum = %.3f\n",sum);sum = add(3,p[1],p[2],p[3]); printf("sum = %.3f\n",sum);free(p);return 0; }
運行結果:
exbot@ubuntu:~/wangqinghe/DeBug/20190702$ ./sum 10 20 30 40 50 60 70
float : p[2] = 20.000
float : p[4] = 40.000
float : p[6] = 60.000
0 argument is 0.000
sum = 0.000
0 argument is 0.000
1 argument is 0.000
sum = 20.000
0 argument is 0.000
1 argument is 0.000
2 argument is 0.000
sum = 20.000
結論:可變參數的輸入類型要和使用的一致。(暫定)。
函數介紹:
va_list
這是一個適用于 va_start()、va_arg() 和 va_end() 這三個宏存儲信息的類型。
一般情況下va_list所定義變量為字符指針,即typedef char *va_list
該類型的變量用于存儲參數的地址。因為得到參數的地址之后,再結合參數的類型,才能得到參數的值。
?
va_start
宏原型是:
void va_start(va_list ap, last_arg)
參數:
ap是一個 va_list 類型的對象,它用來存儲通過 va_arg 獲取額外參數時所必需的信息。
last_arg是最后一個傳遞給函數的已知的固定參數。?
該宏與 va_arg 和 va_end 宏是一起使用的,且必須在使用 va_arg 和 va_end 之前被調用。
?
va_arg
宏原型是:
type va_arg(va_list ap, type)
其作用是從ap開始取一個type型的值返回,并且自動將ap指向下一個參數。所以如果參數類型寫錯了,例如將char*寫成char了,本來要取4個字節,結果只取了一個字節,ap本來要向后面移動4個字節,結果只移動了一個字節,后面的數據就全錯了。
參數:
ap是一個 va_list 類型的對象,存儲了有關額外參數和檢索狀態的信息。該對象應在第一次調用 va_arg 之前通過調用 va_start 進行初始化。
type這是一個類型名稱。該類型名稱是作為擴展自該宏的表達式的類型來使用的。?
返回值:該宏返回下一個額外的參數,是一個類型為 type 的表達式。
?
注意:
va_arg宏的第2個參數不能被指定為char、short或者float類型。
因為char和short類型的參數會被轉換為int類型,而float類型的參數會被轉換為double類型。如果錯誤的指定了,將會在程序中引起麻煩。
例如,這樣寫肯定是不對的:
c = va_arg(ap,char);
因為我們無法傳遞一個char類型參數,如果傳遞了,它將會被自動轉化為int類型。上面的式子應該寫成:
c = va_arg(ap,int);
va_end
宏原型為:
void va_end(va_list ap)
參數:
ap是之前由同一函數中的 va_start 初始化的 va_list 對象。?
其作用是作用是將ap設置為NULL,如果在從函數返回之前沒有調用 va_end,則結果為未定義。
?
總結
使用可變長參數的步驟:
?
1.聲明va_list變量;
2.使用va_start指定可變長參數的位置;
3.使用va_arg來獲取參數值;
4.可選,使用va_end將va_list清零。
?
參考原文:https://blog.csdn.net/hmxz2nn/article/details/80445770
?