设为首页 加入收藏

TOP

va_start、va_arg、va_end、va_copy 可变参函数
2015-07-20 17:46:38 来源: 作者: 【 】 浏览:2
Tags:va_start va_arg va_end va_copy 可变 函数


1、应用与原理

C语言中又是我们无法给出一个函数参数的列表,比如:
  int printf(const char *format, ...);  int fprintf(FILE *stream, const char *format, ...);
这是我们使用到了可以变参数,也就是使用...代表0个或多个参数。 那么编译器如何获取/使用这些参数。这涉及到参数的传递原理: 参数传递原理: 在内存中,函数的参数以栈的方式存取,从右到左入栈。这些参数存放的地址是连续的。这样,我们就可以通过获取第一个参数的地址,以及各个参数的地址偏移量,就可以获取每个参数的地址,从而得到每一个参数。

2、va_start、va_arg、va_end、va_copy介绍

       #include 
          void va_start(va_list ap, last);       type va_arg(va_list ap, type);       void va_end(va_list ap);       void va_copy(va_list dest, va_list src);
va_list是一个指向参数首地址的指针,
typedef struct {char *a0; /* pointer to first homed integer argument */int offset; /* byte offset of next parameter */} va_list;
va_start 对ap进行了一系列的初始化,之后ap会被va_arg和va_end使用到。last是可变参数...的前一个参数,如fun(char *fmt, ...) 中的fmt。通过va_start初始化ap,我们就获得了可变参数前一个参数fmt的地址。 va_arg
va_arg用于获取可变参数...的每一个参数。如函数fun(char *fmt, ...)的一次调用fun(fmt, arg1, arg2, arg3)。在使用va_start()进行ap的初始化后,我们调用一次va_arg(ap,type)就获得了参数arg1,在调用一次就获得arg2,……从而,得到每一个参数的值。
va_end va_end用于清理ap的值,与va_start()配对使用。 va_copy 不常用,暂不介绍。

3、Example

先给一个man手册里的例子
//foo.c#include 
   #include 
   voidfoo(char *fmt, ...){   va_list ap;   int d;   char c, *s;   va_start(ap, fmt);   while (*fmt)       switch (*fmt++) {       case 's':              /* string */           s = va_arg(ap, char *);           printf("string %s\n", s);           break;       case 'd':              /* int */           d = va_arg(ap, int);           printf("int %d\n", d);           break;       case 'c':              /* char */           /* need a cast here since va_arg only           /* need a cast here since va_arg only              takes fully promoted types */           c = (char) va_arg(ap, int);           printf("char %c\n", c);           break;       }   va_end(ap);}

//main.c#include 
   #include 
   #include "foo.h"intmain(void){        foo("%s %d %c %d %c", "Hello", 4, 'x', 3, 'y');        return 0;}
执行结果:
windeal@ubuntu:~/Windeal/apue$ ./exe string Helloint 4char xint 3char ywindeal@ubuntu:~/Windeal/apue$
使用vsprintf的例子
//foo.c#include 
   #include 
   voidfoo(char *fmt, ...){        va_list ap;        int len = 0;        char buf[64];        va_start(ap, fmt);        len = vsnprintf(buf, 128, fmt, ap);        va_end(ap);        int i = 0;        for(i = 0; i < len; i++)        {                putchar(buf[i]);        }        return ;}~
// main.c#include 
   #include 
   #include "foo.h"intmain(void){        foo("Test:%s %d %c %d %c\n", "Hello", 4, 'x', 3, 'y');        return 0;}
执行结果:
windeal@ubuntu:~/Windeal/apue$ ./exe Test:Hello 4 x 3 y
































】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇uva 1399 - Puzzle(AC自动机) 下一篇uva 11475 - Extend to Palindrom..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何在 C 语言中管理 (2025-12-25 03:20:14)
·C语言和内存管理有什 (2025-12-25 03:20:11)
·为什么C语言从不被淘 (2025-12-25 03:20:08)
·常用meta整理 | 菜鸟 (2025-12-25 01:21:52)
·SQL HAVING 子句:深 (2025-12-25 01:21:47)