函数中的可变参数传递原理

 
基本知识:
   我们经常在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 <stdio.h> 
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_list            vargs;
       char_t            *buf;
       int                  rc;
 
       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 <stdio.h>
#include <string.h>
#include <stdarg.h>
/* 函数原型声明,至少需要一个确定的参数,注意括号内的省略号 */
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;
       }
运行结果:
 

本文出自 “技术成长,不断进步!” 博客,转载请与作者联系!

你可能感兴趣的:(函数,职场,可变参数,休闲,传递原理)