格式化输出
格式化数据写入字符串缓冲区
str:指向目标字符串缓冲区的指针 size:缓冲区大小
format:格式化字符串 ...:可变参数列表
//自动截断并添加'\0' int snprintf(char *str, size_t size, const char *format, ...);
动态分配缓冲区
/*如果成功,vsnprintf 返回假设缓冲区无限大时,本应写入的字符数(不包括结尾的空字符 \0)。这个返回值非常有用!如果编码错误(例如格式字符串无效),则返回一个负数。*/ int vsnprintf(char *str, size_t size, const char *format, va_list ap); /*返回值 n 代表了格式化后字符串的真正长度。如果 n < size:说明字符串被完整地写入了缓冲区。如果 n >= size:说明缓冲区空间不足,输出被截断了。缓冲区 str 中包含了 size - 1 个字符,并以 \0 结尾。*/
*char str:指向一个字符数组的指针,用于存储格式化后的字符串。也就是结果存放的缓冲区。 size_t size:缓冲区 str 的总大小(以字节为单位)。这是该函数安全性的关键,它确保写入的字符数不会超过这个大小(包括结尾的空字符 \0)。 *const char format:格式化字符串,与 printf、sprintf 的用法完全相同。它指定了如何格式化后续的参数(例如 %d, %s, %.2f)。 va_list ap:这是一个已经初始化过的可变参数列表变量。它'承载'了要传递给 format 的实际参数。
核心用途与用法
vsnprintf 的核心用途是:安全地格式化字符串,并且它通常用于编写你自己的可变参数函数(即包装类函数)。最常见的场景是你想创建一个类似 printf 的函数,比如用于日志记录、错误输出等。
为什么不用 snprintf?你可以直接在你的可变参数函数里调用 snprintf。但 vsnprintf 的存在允许你将可变参数逻辑(va_start, va_end)与格式化逻辑分离,使代码更清晰。更重要的是,如果你的自定义函数需要多次使用这些可变参数(例如,先计算长度,再分配内存,最后写入),va_list 可以传递,而 ... 形式的参数不能直接重复使用。
#include <stdio.h>
#include <stdlib.h>
int create_message(char **msg, const char *format, ...) {
va_list args;
// 第一次调用获取所需长度
va_start(args, format);
int len = vsnprintf(NULL, , format, args);
va_end(args);
(len < ) ;
*msg = (len + );
(!*msg) ;
va_start(args, format);
vsnprintf(*msg, len + , format, args);
va_end(args);
;
}


