可变函数定义及使用

来源:互联网 发布:手机用户mac绑定错误 编辑:程序博客网 时间:2024/06/01 19:00

关键词:

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=0xbff66ac4printf("&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=0xbff66ac8printf("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=0xbff66ad0return 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 0int 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);}#endiffor(; 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.000000000argptr = 0xbfa0ef6c, *argptr = 0.000000000argptr = 0xbfa0ef74, *argptr = 0.000000000argptr = 0xbfa0ef7c, *argptr = 0.000000000sum of series is 0.937540

有一处警告,且输出打印不对

printf("argptr = %p, *argptr = %10.9f\n", argptr, *((double*)argptr));这样就对了

0 0
原创粉丝点击