linux 不定参数传递,函数中的可变参数传递原理

基本知识:

我们经常在LINUX代码中看到传递不定参数的函数,这是怎样实现的呢?

我们可以通过在头文件stdarg.h中定义的va_start(), va_arg(),va_end()这几个函数来实现。在/opt/buildroot-gcc342/lib/gcc/mipsel-linux-uclibc/3.4.2/include目录下找到了stdarg.h,值得注意的是,这三个函数是在gcc编译器中定义的,而不是内核或C库中的定义的。

它们的作用是:

va_start

使argp指向第一个可选参数。注意是第一个可选参数,而不是第一个参数。

va_arg

返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。

va_end

把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。

基本原理

关于stdarg.h中的定义,我并没有去深究。我想其基本原理可以用下面的这段代码来说明。

#include

void fun(int a, ...)

{

int *temp = &a;

temp++;

int i=0;

for(i = 0; i < a; ++i)

{

printf("%d\n", *temp);

temp++;

}

}

int main()

{

int a = 1;

int b = 2;

int c = 3;

int d = 4;

fun(4, a, b, c, d);

return 0;

}

stdarg.h与上面代码不同之处,我的理解是,va_start,和va_end的作用,有点像进入临界区的意思,在这个临界区内,不允许其他进程的内存操作。

应用实例

例如,在我们是实际应用中goahead开源软件中用到的这段代码:

int websWrite(webs_t wp, char_t *fmt, ...)

{

va_listvargs;

char_t*buf;

intrc;

a_assert(websValid(wp));

va_start(vargs, fmt);

buf = NULL;

rc = 0;

if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {

trace(0, T("webs: websWrite lost data, buffer overflow\n"));

}

va_end(vargs);

a_assert(buf);

if (buf) {

rc = websWriteBlock(wp, buf, gstrlen(buf));

bfree(B_L, buf);

}

return rc;

}

下面再给个例子。

#include

#include

#include

/*函数原型声明,至少需要一个确定的参数,注意括号内的省略号*/

int demo(char[], ...);

int main(void)

{

demo("DEMO", "This", "is","a", "demo!", "");

return 0;

}

/*ANSI标准形式的声明方式,括号内的省略号表示可选参数*/

int demo(char msg[], ... )

{

/*定义保存函数参数的结构*/

va_list argp;

int argno = 0;

char *para;

/*argp指向传入的第一个可选参数,msg是最后一个确定的参数*/

va_start(argp, msg );

while (1)

{

para = va_arg( argp, char *);

if ( strcmp( para, "") == 0 )

break;

printf("Parameter #%d is:%s\n",argno,para);

argno++;

}

va_end( argp );

/*将argp置为NULL*/

return 0;

}

运行结果:

61660ff5827dd7e917a89b66c010c04a.bmp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值