可變函數定義及使用

關鍵詞:

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));這樣就對了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章