文章目录
1. va_list变量介绍
- 使用前需引用头文件<stdarg.h>
- va_list 类型本质是typedef char * va_list
- va_list类型声明一个变量(char * ),假设这里声明va_list pArgs,该字符指针变量将依次指向后续待传入的各参数(无名参数…)
- 宏va_start将pArgs初始化为指向第一个无名参数(无名参数…),在使用pArgs之前,必须用该宏调用一次。函数参数表中至少包括一个有名参数 (const char *pszFormat,…)
- 每次调用va_arg,该宏都将会返回当前pArgs指向的参数,并将pArgs指向下一个参数,va_arg使用一个类型名来决定返回的对象类型、指针移动的步长。
- 最后,必须在函数返回之前调用va_end,来完成一些必要的清理工作
1.1 基于上面的介绍,实现一个简化版本printf函数
#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
//这里只实现了打印%d,%f,%s
void minprintf(char *fmt, ...)
{
va_list pArgs; /* 依次指向每个未命名参数... */
char *p, *sval;
int ival;
double dval;
va_start(pArgs, fmt); /* 初始化pArgs,使pArgs指向第一个未命名参数*/
for (p = fmt; *p; p++)
{
if (*p != '%')
{
putchar(*p);
continue;
}
switch (*++p) //先进行++操作,为了取到%符号后面的字符d,f,s等
{
case 'd':
ival = va_arg(pArgs, int);
printf("%d", ival);
break;
case 'f':
dval = va_arg(pArgs, double);
printf("%f", dval);
break;
case 's':
for (sval = va_arg(pArgs, char *); *sval; sval++)
putchar(*sval);
break;
default:
putchar(*p);
break;
}
}
va_end(pArgs); /* 完成后,清理工作 */
}
2. 其它涉及va_list函数的应用
2.1 vsprintf格式化函数的应用
/**************************************************************************************************
C 库函数 int vsprintf(char *str, const char *format, va_list arg) 使用参数列表发送格式化输出到字符串。
*****************************************************************************************************/
int PrintMessage(char *format,...)
{
int nRet = 0;
char buf[80] = { 0 };
va_list pArgs;
va_start(pArgs, format); //字符指针pArgs指向参数列表第一个未名参数(即format格式化所对应的...实际参数)
nRet = vsprintf(buf, format, pArgs); //格式化到buf中
va_end(pArgs); //清理工作
printf("%s\n", buf);
return nRet;
}
void main(void)
{
int i = 10;
float f = 20.4;
char *str = "hello world";
PrintMessage("i = %d; f = %f; str = %s", i, f, str);
}
2.2 vsprintf_s格式化函数的应用
/**************************************************************************************************
int vsprintf_s(char * _DstBuf, size_t _SizeInBytes, const char * _Format, va_list _ArgList);
*****************************************************************************************************/
void PrintMessage_s(const char *pszFormat,...)
{
char buf[512] = { 0 };
va_list pArgs;
va_start(pArgs, pszFormat); //初始化,pArgs指向有参列表...的第一个未名参数
vsprintf_s(buf, sizeof(buf), pszFormat, pArgs); //格式化到buf中
va_end(pArgs); //格式化完成后,清理工作
printf("%s\n", buf);
}
void main(void)
{
int a = 10;
float f = 30.5;
char *str = "hello world";
PrintMessage_s("a = %#x, f = %f, str = %s\n", a, f, str);
}
3. 参考文献
《菜鸟教程C库函数—vsprintf》
《The_c_Programming_Language》第二版中文版_第7章 输入与输出_7.3变长参数