C 的可变参数
来源:互联网 发布:龙芯支持windows 编辑:程序博客网 时间:2024/04/20 14:45
1 可变参数的函数
最初,C中只有函数支持可变参数,例如最常见的printf系列函数,其声明如下:
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
要实现自己的支持可变参数的函数,需要用到下面几个宏:#include <stdarg.h>
void va_start(va_list ap, last); /*功能:用可变参数前的最后一个参数last初始化ap*/
type va_arg(va_list ap, type); /*功能:返回ap后面type类型的参数*/
void va_end(va_list ap); /*功能:终止ap使用*/
void va_copy(va_list dest, va_list src);/*功能:把src拷贝给dest*/
定义:
typedef char *va_list;
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (ap = (va_list) NULL)
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
其中,acpi_native_int定义为typedef s32acpi_native_int;或typedef s64 acpi_native_int;
示例:实现自己的printf函数(转载)void print(char* fmt, ...){ double vargflt = 0; int vargint = 0; char* vargpch = NULL; char vargch = 0; char* pfmt = NULL; va_list vp; va_start(vp, fmt); pfmt = fmt; while(*pfmt) { if(*pfmt == '%') { switch(*(++pfmt)) { case 'c': vargch = va_arg(vp, int); /* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */ .....; break; case 'd': case 'i': vargint = va_arg(vp, int); .......; break; case 'f': vargflt = va_arg(vp, double); /* va_arg(ap, type), if type is narrow type (char, short, float) an error is given in strict ANSI mode, or a warning otherwise.In non-strict ANSI mode, 'type' is allowed to be any expression. */ .......; break; case 's': vargpch = va_arg(vp, char*); .......; break; case 'b': case 'B': vargint = va_arg(vp, int); ......; break; case 'x': case 'X': vargint = va_arg(vp, int); ......; break; case '%': putchar('%'); break; default: break; } pfmt++; } else { putchar(*pfmt++); } } va_end(vp);}
后来,C99编译器既支持可变参数的函数,也支持可变参数的宏:
2 可变参数的宏
#define debug(fmt, …) printf(fmt,__VAR_ARGS__) /*支持可变参数的宏*/
#define debug(fmt, …) printf(fmt,##__VAR_ARGS__) /*支持可变参数的宏,其中可变参数可以为空*/
#define debug(fmt, arg…) printf(fmt,##arg) /*GCC支持给可变参数一个名字,如arg 。当可变参数为空时,##操作使预处理器去除掉它前面的逗号*/
2.1 说明
<1> ... 表示可变参数
<2> __VAR_ARGS__ 保留名,将可变参数 ... 传给宏
<3> arg 可变参数名,代表可变参数列表
2.2 示例
#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#define FMT_WARN(fmt...) do {if(0) printf(fmt);}while(0)void _log(const char *domain, const char *file, const char *function, int line, int level, const char *fmt, ...){ va_list arg; va_start(arg, fmt); printf(" domain: %s\n", domain); printf(" file: %s\n", file); printf("function: %s\n", function); printf(" line: %d\n", line); printf(" level: %d\n", level); vprintf(fmt, arg); va_end(arg);}#define log(dom,level,fmt...) do{ \ FMT_WARN(fmt); \ /*说明:当fmt为空时,编译会出错*/ _log(dom, __FILE__, __FUNCTION__, __LINE__, level, ##fmt); \}while(0)#define log_rate(fmt, ...) ({ \ /*printf(fmt);*/ \ /*printf("%d -- %s -- %d\n",__VA_ARGS__);*/ \ log(fmt, ##__VA_ARGS__); \ /*说明:log_rate的参数fmt对应log的dom,可变参数 ... 与log的其他参数对应*/ })
- C的可变参数
- C 的可变参数
- C语言的可变参数
- C的可变参数传入
- 可变参数的C函数
- 学习C的可变参数
- C语言的可变参数
- c语言的可变参数
- 学习C的可变参数
- C函数的可变参数
- C可变参数的函数
- 关于c的可变参数
- c语言的可变参数
- C语言的可变参数
- C 可变参数的使用
- C可变参数的使用
- C可变参数的实现
- c 可变参数 定义可变参数的函数
- php js rsa
- 第N次重装树莓派3:记录全过程
- CSS 高端进阶 - LESS
- Qt学习之路(12): 菜单和工具条
- APUE 1-3程序,列出一个目录中的所有文件
- C 的可变参数
- 在windows上安装Rabbit MQ的详细步骤
- UI开发设计
- css定位中position:absolute与float的区别
- 我想用oracle数据库中分别提取出date年月日和时间,该怎么写?
- zookeeper学习
- UIView旋转动画
- Qt学习之路(13): 菜单和工具条(续)
- 不使用“+”“-”操作符计算两数之和