不定参数处理 va_list和vsnprintf

      在对常用宏 带小练习的掌握基础上,研究一下变参函数的参数处理。

1:va_list及相关宏定义

      va_list表示可变参数列表类型,指向参数的指针。

//获取类型占用的空间长度,最小占用长度为int的整数倍
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

//获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数)
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

//获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型)
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

//清空va_list可变参数列表
#define va_end(ap) ( ap = (va_list)0 )

1.1:原理

    对于多参数函数test(char *para1,char *param2,char *param3, char *param4,...),在该函数体内用va_list处理各个参数。

    在linux中,参数由右向左入栈,栈从高地址向低地址走,如下图:

 调用va_start(list,param1) 时:list指针指向情况对应下图:

2:vsnprintf

_vsnprintf是C语言库函数之一,属于可变参数。用于向字符串中打印数据、数据格式用户自定义。

#include <stdarg.h>

int _vsnprintf(char* str, size_t size, const char* format, va_list ap);

参数说明:

  1. char *str [out],把生成的格式化的字符串存放在这里.

  2. size_t size [in], str可接受的最大字符数 [1]  (非字节数,UNICODE一个字符两个字节),防止产生数组越界.

  3. const char *format [in], 指定输出格式的字符串,它决定了你需要提供的可变参数的类型、个数和顺序。

  4. va_list ap [in], va_list变量. va:variable-argument:可变参数

函数功能:将可变参数格式化输出到一个字符数组。

用法类似于vsprintf,不过加了size的限制,防止了内存溢出(size为str所指的存储空间的大小)。

返回值:执行成功,返回最终生成字符串的长度,若生成字符串的长度大于size,则将字符串的前size个字符复制到str,同时将原串的长度返回(不包含终止符);执行失败,返回负值,并置errno。

备注:

linux环境下是:vsnprintf

VC6环境下是:_vsnprintf

 

练习如下:

#include <stdio.h>
#include <stdarg.h>
#define BUF_MAX 1024
void mylog(const char *fmt, ...) {
	char buf[BUF_MAX] = {0};
	va_list vl;

	va_start(vl, fmt);
	vsnprintf(buf, BUF_MAX, fmt, vl);
	va_end(vl);
	printf("%s", buf);
}
void debug(int module, const char *fmt, ...) {
	char buf[512] = {0};
	va_list vl;

	va_start(vl, fmt);
	vsnprintf(buf, sizeof(buf), fmt, vl);
	va_end(vl);
	mylog("%s%s:LINE:%d, FUNCTION:%s, module:%d: %s",
		__DATE__, __TIME__, __LINE__, __func__, module, buf);
}

static int number = 0;
#define DBG(fmt,...)     \
	do {\
		debug(number++, fmt, __VA_ARGS__);\
	   } while(0)


int main () {
	for(int i1 = 1; i1 < 10 ; i1++)
		DBG("the number is: %d\n", i1);

	printf("well done!\n");
	return 0;
}

输出:

Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:0: the number is: 1
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:1: the number is: 2
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:2: the number is: 3
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:3: the number is: 4
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:4: the number is: 5
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:5: the number is: 6
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:6: the number is: 7
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:7: the number is: 8
Jul 23 202006:36:10:LINE:21, FUNCTION:debug, module:8: the number is: 9
well done!

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值