【C语言】vsnprintf函数的使用

vsnprintf函数是C语言中用于格式化字符串的函数,它接受一个va_list参数来处理可变长度的参数列表。文章通过两个示例展示了如何使用vsnprintf,包括如何在函数中传递可变参数,并强调了其灵活性和安全性,如防止缓冲区溢出。
摘要由CSDN通过智能技术生成

标题【C语言】vsnprintf函数的使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

`在学习stm32串口打印的时候遇到这个vsnprintf函数

    unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);		//vsnprintf()格式化
	va_end(ap);

在这里插入图片描述

一、vsnprintf是什么?

该函数是一个标准的 C 函数,用于格式化字符串并将生成的字符存储在缓冲区中。它与函数类似,但有一个关键区别:函数不是直接采用可变长度的参数列表,而是采用参数,该参数是已使用宏初始化的参数列表。

vsnprintf 函数的原型通常定义如下:

#include <stdio.h>  
#include <stdarg.h>  
  
int vsnprintf(char *str, size_t size, const char *format, va_list ap);

str:指向一个字符数组的指针,该数组用于存储格式化的字符串。
size:str 指向的数组的大小(以字节为单位)。这是为了防止缓冲区溢出。
format:格式字符串,指定了后续参数如何被格式化为字符串。这个字符串遵循与 printf 相同的格式说明符。
ap:一个 va_list 类型的变量,它包含了要格式化的可变数量的参数。这个列表是通过 va_start 宏初始化的,并且可以通过 va_arg 宏来访问其中的参数。
返回值:

vsnprintf 函数返回写入的字符数(不包括终止的空字符 ‘\0’),但不包括由于缓冲区大小限制而未写入的字符数。如果发生错误,则返回负值。

使用 vsnprintf 的一个典型场景是当你需要从一个函数内部调用 printf 风格的函数,但这个函数需要接受一个可变的参数列表时。通过使用 va_list 和 vsnprintf,你可以构建一个灵活的函数,它能够处理任意数量和类型的参数。

然而,需要注意的是,由于 vsnprintf 需要你手动管理 va_list,因此它的使用相对于 snprintf 来说更为复杂和低级。在大多数情况下,如果你可以直接知道要格式化的参数,那么使用 snprintf 会更加简单和直接,比如下面的示例1的情况。

二、例子

1.示例1

代码如下(示例):

#include <stdio.h>
#include <stdarg.h>

void my_printf(char *str, ...) {
    char buffer[100];
    int len;
    va_list args;

    va_start(args, str);
    len = vsnprintf(buffer, sizeof(buffer), str, args);
    va_end(args);

    printf("Result: %s, length: %d\n", buffer, len);
}

int main() {
    my_printf("The answer is %d", 42);
    my_printf("My name is %s and my age is %d", "Alice", 25);

    return 0;
}

在这个例子中,我们定义了一个函数’my_printf(这需要一个格式字符串’strstr和可变数量的参数。在函数内部,我们声明了一个字符缓冲区 buffer大小为 100 字节,我们使用va_start()宏初始化一个 'VAva_list对象 'args’ 。

然后我们调用 'vsnprintf(使用三个参数:用于存储结果字符串的缓冲区buffer,缓冲区的最大大小(sizeof(buffer)),以及格式字符串str和va_list对象args.这允许我们将可变数量的参数传递给vsnprintf()使用 args对象。

在调用 va_end()宏来清理’参数args对象。

最后,在 'main()my_printf()两次不同设置字符串格式和参数列表。这第一次调用格式化整数值 42,以及第二次调用设置字符串格式"Alice"和整数值25.

当我们运行这个程序时,我们得到以下输出:

Result: The answer is 42, length: 16
Result: My name is Alice and my age is 25, length: 33

总结

vsnprintf函数用于将一组变长参数格式化为一个字符串,并将其存储到一个字符缓冲区buffer中。与sprintf()函数不同的是,vsnprintf()函数使用一个va_list参数,该参数包含要格式化的变长参数列表。这使得vsnprintf()函数更加灵活,可以根据需要在运行时传递变长参数列表,而不需要在编译时指定参数类型和数量。你可以传递4个,5个不同类型的参数,而且不用在函数定义的时候规定参数类型和数量。

虽然可以传递的参数数量有很多个,但也是有限制的,限制通常是由堆栈的大小或可用内存施加的,而不是由函数本身施加的。vsnprintf()
该函数接受可变数量的参数,这些参数通过对象传递给它。对象的大小由传递给它的参数的数量和大小决定va_list如果尝试将过多参数传递给vsnprintf() ,则可能会遇到堆栈溢出错误或内存不足。确切的限制将取决于平台和可用资源。

但是在实践中,很少遇到此限制,因为大多数程序不需要将大量参数传递给vsnprintf() 。如果您发现需要将大量参数传递给vsnprintf() ,则可能需要考虑重构代码以使用更节省内存的其他方法。

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值