關鍵詞:
stdarg.h頭文件
va_list
va_start
va_arg
va_end
1.定義可變參數函數
#include<stdarg.h>
返回類型 函數名(參數類型1 參數1, 參數類型2 參數2, ...)
例如:
int func(int i, ...)
int func(int i, int j, int k, ...)
2.獲取參數
va_list parg //定義parg指針
va_start(parg, i) //初始化parg指針,執行後parg->j
va_arg(parg, int) //獲取參數,這裏參數類型可以爲別的float等等可以與i類型不同,pargs會按此類型存儲的長度取數據,並移位,因爲執行va_start(parg, i) 後parg->j,則執行//va_arg(parg, int) ,parg按整形int取4個字節
3.清理
va_end(parg) //可變函數返回前調用
實列:
addnum(1,2,3,4,0) //實現1:求和1+2+3+4 0表示結束取值(當然可以爲其它特殊數-1等等),循環加的時候遇到0表示參數結束(加結束)
addnum(4,1,2,3,4)//實現2:有4個數1,2,3,4求和
sum_series(4, 0.5, 0.25, 0.125, 0.06254)//有4個小數0.5, 0.25, 0.125, 0.06254求這4個數的和
代碼1:
#include<stdio.h>
#include<stdarg.h>
int addnum(int i, ...)
{
va_list parg;
va_start(parg, i); //i=1,&1=0xbff66ac0,執行va_start後parg=0xbff66ac4
printf("&i = %p, parg = %p\n", &i, parg); //打印地址:&i = 0xbff66ac0, parg=0xbff66ac4 數據2地址
int num =i ;
int v = va_arg(parg, int);//開始parg=0xbff66ac4,從0xbff66ac4處取4個字節數據給v,即v=2,此後parg=0xbff66ac8
printf("parg = %p\n,", parg); //打印地址:parg=0xbff66ac8 數據3地址
while( v !=0) //取到的數據爲0後不往下取數據
{
num = num + v;
v = va_arg(parg, int);//依次取3 4 0printf("parg = %p\n", parg);//依次打印4,0,*,地址:parg=0xbff66acc 數據4地址
//parg=0xbff66ad0 數據0地址
//parg=0xbff66ad4,
}
va_end(parg);
return num;
}
int main()
{
printf("%d\n", addnum(1,2,3,4,0));//1,2,3,4,0在棧中,&1=0xbff66ac0,&2=0xbff66ac4,&3=0xbff66ac8,&4=0xbff66acc,&0=0xbff66ad0
return 0;
}
cc addnum.c
./a.out
&i = 0xbff66ac0, parg = 0xbff66ac4parg = 0xbff66ac8,parg = 0xbff66accparg = 0xbff66ad0parg = 0xbff66ad410
由運行結果可知:
高地址:最後一個參數
。。。。
低地址:第一參數
具體可參考:
點擊打開鏈接中參數在棧中的分佈
若想了解更具體可以參考此blog地址:
http://blog.csdn.net/chchchdx123/article/details/7597149
或下面鏈接:
代碼2:
基於代碼1改進:
#include<stdio.h>
#include<stdarg.h>
int addnum(int i, ...)
{
va_list parg;
va_start(parg, i);
printf("&i = %p, parg = %p, *parg = %d\n", &i, parg, *parg);
int num=0, v;
#if 0
int num =i ;
int v = va_arg(parg, int);
printf("parg = %p\n,", parg);
while( v !=0)
{
num = num + v;
v = va_arg(parg, int);
printf("parg = %p\n", parg);
}
#endif
for(; i; i--)
{
printf("parg = %p, *parg = %d\n", parg, *parg);
v = va_arg(parg, int);
num +=v;
}
va_end(parg);
return num;
}
int main()
{
// printf("%d\n", addnum(1,2,3,4,0));
printf("%d\n", addnum(4,1,2,3,4));
return 0;
}
結果:
root@book-desktop:/work/video_example# cc addnum.c
root@book-desktop:/work/video_example# ./a.out
&i = 0xbfd09e50, parg = 0xbfd09e54, *parg = 1
parg = 0xbfd09e54, *parg = 1
parg = 0xbfd09e58, *parg = 2
parg = 0xbfd09e5c, *parg = 3
parg = 0xbfd09e60, *parg = 4
10
對比代碼1和代碼2可知代碼2簡潔,易理解
代碼3:
#include<stdio.h>
#include<stdarg.h>
double sum_series(int num, ...)
{
double sum=0.0, t;
va_list argptr;
va_start(argptr, num);
for( ; num; num--)
{
printf("argptr = %p, *argptr = %10.9f\n", argptr, *argptr);
t = va_arg(argptr, double);
sum +=t;
}
va_end(argptr);
return sum;
}
int main()
{
double d;
d = sum_series(4, 0.5, 0.25, 0.125, 0.06254);
printf("sum of series is %f\n", d);
return 0;
}
root@book-desktop:/work/video_example# cc doublesum.c
doublesum.c: In function ‘sum_series’:
doublesum.c:11: warning: format ‘%10.9f’ expects type ‘double’, but argument 3 has type ‘int’
root@book-desktop:/work/video_example# ./a.out
argptr = 0xbfa0ef64, *argptr = 0.000000000
argptr = 0xbfa0ef6c, *argptr = 0.000000000
argptr = 0xbfa0ef74, *argptr = 0.000000000
argptr = 0xbfa0ef7c, *argptr = 0.000000000
sum of series is 0.937540
有一處警告,且輸出打印不對
printf("argptr = %p, *argptr = %10.9f\n", argptr, *((double*)argptr));這樣就對了