c语言中的可变参数编程
2013-05-30 21:10
155 查看
在c语言中使用变长参数最常见的就是下面两个函数了:
那他们是怎样实现支持变成参数的呢?在使用变长参数的函数(这里假设是func)实现部分其实用到了stdarg.h里面的多个宏来访问那些不确定的参数,它们分别是:
假设lastarg是func的最后一个具名参数,即在func函数定义中...之前的那个参数(在printf中lastarg是format),在func中首先定义一个变量:
这个变量以后会依次指向各个可变参数。ap在使用之前必须用宏va_start初始化一次,如下所示:
其中lastarg是func中的最后一个具名参数。然后就可以用va_arg来获得下一个不定参数(前提是知道这个不定参数的类型type):
最后就是用宏va_end来清理现场。
下面我们来自己实现一个可变参数的函数:
输出结果:
可以看到上面的程序完成按我们的意愿实现了变长参数的访问,通过前面的fmt来控制下一个不定参数的类型。那这三个宏是怎样实现对不定参数访问的呢?下面来看看它们是怎么实现的:
va_list实际就是一个指向各个不定参数的指针,由于参数的类型是不确定的,所以可以定义va_list为void *或者char *类型,即
va_start就是将va_list指向函数最后一个具名参数lastarg后面的位置,这个位置就是第一个不定参数。
va_arg获取当前不定参数的值,根据当前参数的类型的大小移动指针指向下一个不定参数。
va_end将指针清0。
本质上其实就是靠前面lastarg来控制不定参数的类型,va_list变量来指向不定参数的地址,然后根据lastarg一个一个的获取不定参数。
int printf(const char *format, ...); int scanf(const char *format, ...);
那他们是怎样实现支持变成参数的呢?在使用变长参数的函数(这里假设是func)实现部分其实用到了stdarg.h里面的多个宏来访问那些不确定的参数,它们分别是:
void va_start(va_list ap, last); type va_arg(va_list ap, type); void va_end(va_list ap);
假设lastarg是func的最后一个具名参数,即在func函数定义中...之前的那个参数(在printf中lastarg是format),在func中首先定义一个变量:
va_list ap
这个变量以后会依次指向各个可变参数。ap在使用之前必须用宏va_start初始化一次,如下所示:
va_start(ap, lastarg);
其中lastarg是func中的最后一个具名参数。然后就可以用va_arg来获得下一个不定参数(前提是知道这个不定参数的类型type):
type next = va_arg(ap, type)
最后就是用宏va_end来清理现场。
下面我们来自己实现一个可变参数的函数:
#include <stdio.h> #include <stdarg.h> void func(char *fmt, ...) { va_list ap; va_start(ap, fmt); while (*fmt) { switch(*fmt) { case 'd': fprintf(stdout, "%d\n", (int)va_arg(ap, int)); break; case 'c': fprintf(stdout, "%c\n", (char)va_arg(ap, int)); break; case 's': fprintf(stdout, "%s\n", (char *)va_arg(ap, char *)); break; default: fprintf(stderr, "error fmt\n"); } fmt ++; } va_end(ap); } int main ( int argc, char *argv[] ) { func("dcs", 10, 's', "hello"); return 0; } /* ---------- end of function main ---------- */
输出结果:
10 s hello
可以看到上面的程序完成按我们的意愿实现了变长参数的访问,通过前面的fmt来控制下一个不定参数的类型。那这三个宏是怎样实现对不定参数访问的呢?下面来看看它们是怎么实现的:
va_list实际就是一个指向各个不定参数的指针,由于参数的类型是不确定的,所以可以定义va_list为void *或者char *类型,即
#define va_list void *
va_start就是将va_list指向函数最后一个具名参数lastarg后面的位置,这个位置就是第一个不定参数。
#define va_start(ap, lastarg) \ (ap = (va_list)&lastarg + sizeof(lastarg))
va_arg获取当前不定参数的值,根据当前参数的类型的大小移动指针指向下一个不定参数。
#define va_arg(ap, type) \ (*(type *)((ap += sizeof(type)) - sizeof(type)))
va_end将指针清0。
#define va_end(ap) (ap=(va_list)0)
本质上其实就是靠前面lastarg来控制不定参数的类型,va_list变量来指向不定参数的地址,然后根据lastarg一个一个的获取不定参数。
相关文章推荐
- 编程基础知识学习———C语言中可变参数的用法
- 编程入门:浅谈C语言的可变参数
- C语言:可变参数编程
- C语言中的可变参数函数 三个点“…”printf( const char* format, ...) 博客分类: C语言 ANSI C CC++C#D语言编程 第一篇
- C语言可变参数编程
- c语言可变参数编程
- [转载]编程入门:浅谈C语言的可变参数
- 编程基础知识学习———C语言中可变参数的用法
- C语言可变参数编程之Avg、Myprinf…
- 实现c语言中的可变参数函数
- [C语言]可变参数列表和简单模拟实现printf
- c语言中可变参数的原理---printf
- 8_7 C语言 | 探寻可变参数列表
- C语言 可变参数宏
- 透析C语言可变参数问题
- C语言可变长参数实现原理
- C语言可变参数,参数传递
- C语言可变参数函数取参方法
- C语言的可变参数的实现的原理
- 可变参数(C语言):stdarg.h