C语言中vsnprintf函数的用法详解
标题【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((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);
该函数采用四个参数:用于存储结果字符串的字符缓冲区、缓冲区的最大大小、指定如何设置参数格式的格式字符串以及包含参数本身的变量。va_list
该函数读取格式字符串并处理它找到的任何格式说明符。这些格式说明符告诉函数如何格式化 中的参数。va_list
当它处理每个格式说明符时,该函数会从使用宏中检索下一个参数。va_list va_arg()
该函数根据格式说明符设置参数的格式,并将生成的字符写入缓冲区。如果生成的字符串比缓冲区长,则该函数将停止写入字符,并返回缓冲区较大时应写入的字符数
处理完所有参数并将生成的字符串写入缓冲区后,该函数将返回写入缓冲区的字符数(不包括
'vsnprintf(va_list变量,您可以在运行时将可变长度的参数列表传递给函数,使其比标准更灵活sprintf()功能。
二、例子
1.示例1
代码如下(示例):
#include <stdio.h>
#include <stdarg.h>
int main() {
char buffer[100];
int len;
len = vsnprintf(buffer, sizeof(buffer), "The answer is %d", 42);
printf("Result: %s, length: %d\n", buffer, len);
return 0;
}
在此示例中,我们首先声明一个’缓冲区buffer大小为 100 字节。然后我们调用 'vsnprintf(vsnprintf()使用三个参数:用于存储结果字符串的缓冲区,缓冲区的最大大小(sizeof(buffer)),和格式字符串其中包括一个单一格式说明符 %d表示整数值。
我们通过42作为参数格式说明符通过使用vsnprintf()函数的可变长度参数列表。
最后,我们使用 'printf() 打印生成的字符串及其长度
当我们运行这个程序时,我们得到以下输出:
Result: The answer is 42, length: 18
2.示例2
代码如下(示例):
#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: 18
Result: My name is Alice and my age is 25, length: 32
总结
vsnprintf函数用于将一组变长参数格式化为一个字符串,并将其存储到一个字符缓冲区buffer中。与sprintf()函数不同的是,vsnprintf()函数使用一个va_list参数,该参数包含要格式化的变长参数列表。这使得vsnprintf()函数更加灵活,可以根据需要在运行时传递变长参数列表,而不需要在编译时指定参数类型和数量。你可以传递4个,5个不同类型的参数,而且不用在函数定义的时候规定参数类型和数量。
虽然可以传递的参数数量有很多个,但也是有限制的,限制通常是由堆栈的大小或可用内存施加的,而不是由函数本身施加的。vsnprintf()
该函数接受可变数量的参数,这些参数通过对象传递给它。对象的大小由传递给它的参数的数量和大小决定va_list如果尝试将过多参数传递给vsnprintf() ,则可能会遇到堆栈溢出错误或内存不足。确切的限制将取决于平台和可用资源。
但是在实践中,很少遇到此限制,因为大多数程序不需要将大量参数传递给vsnprintf() 。如果您发现需要将大量参数传递给vsnprintf() ,则可能需要考虑重构代码以使用更节省内存的其他方法。