vsnprintf函数详解-----学习了解

本文详细介绍了vsnprintf函数的功能和使用方法,该函数用于将格式化的可变参数列表写入固定大小的缓冲区,常见于嵌入式系统的调试信息输出。文章提供了具体的代码示例,展示了如何结合va_start和va_end进行参数处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vsnprintf函数:C标准库函数-<starg.h>
(虽然网上说实在stdarg.h中,但是我在arm的stdarg.h中没有看到这个函数,有点疑惑)

int vsnprintf(char *s, size_t n, const char *format, va_list arg)
功能:将格式化的可变参数列表写入大小的缓冲区,如果在printf上使用格式,则使用相同的文本组成字符串,如果使用arg标识的变量则将参数列表中的元素作为字符串存储在char型指针s中。
传参
s:指向存储结果C字符串的缓冲区的指针。
n:要转换的字符的长度(bytes)
formate:可变参数
arg:申请参数列表的变量,标识使用va_start初始化的变量参数列表的值。
返回值
如果n值勾搭,则会写入的字符数,但是不包括’\0’的终止符。如果发生编码错误则返回值小于0.
注:只有返回值是非负而且小于n时,字符串才完全被写入。

注:
vsnprintf函数一般都与va_start和va_end一起使用

实例

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

#define MAXLEN 20

int test_log(char* format, ...)
{
    char str_tmp[MAXLEN];
    int i=0,j=0;
    va_list arg;                           
    va_start (arg, format);                 
    i=vsnprintf(str_tmp, MAXLEN, format, arg);  
    va_end(arg);                            

    printf("%s", str_tmp); 
    return i;
}

void main()
{   
    int i=test_log("This is vsprintf test:%s%d\n","string",1024);    
}

运行结果为:
This is vsprintf test:string1024

嵌入式中这个函数常被用在debug函数中来将打印调试信息,跟调试串口绑定在一起,可以实现可变参的组合输出,想当与实现一个简单的printf函数已供一个debug的接口。
如下:
实际项目中的debug.c的部分实例代码

### C标准库 `vsnprintf` 返回 `-1` 的具体情况及其与 `vsnprintf_s` 的参数差异 #### `vsnprintf` 返回 `-1` 的原因 按照 C99 标准的规定,`vsnprintf` 函数不会返回 `-1`。相反,它会返回生成的完整字符串所需的总字符数(包括终止符 `\0`),即使目标缓冲区不足以容纳全部内容[^1]。如果返回值大于或等于传递给它的 `size` 参数,则表示输出被截断,并且只写了部分字符串到缓冲区中[^2]。 但是需要注意的是,在某些特定条件下或者非标准实现里可能会有例外情况存在。例如当传入非法参数时(比如 NULL 指针作为第一个参数),理论上可能引发未定义行为甚至导致程序崩溃而不是简单地返回负一[^3]。 #### `vsnprintf` 和 `vsnprintf_s` 的参数对比 两者的主要区别在于以下几个方面: - **函数签名** - `vsnprintf`: ```c int vsnprintf(char *str, size_t size, const char *format, va_list ap); ``` - `vsnprintf_s`(Microsoft 特定): ```c errno_t vsnprintf_s( char *buffer, size_t sizeInBytes, size_t count, const char *format, va_list argptr ); ``` - **额外的安全特性** - `vsnprintf_s` 添加了一个新的参数 `count`,用于指定最多能写入多少个字符(不计结尾处自动加入的空字符)。这样做的目的是为了进一步加强防护措施来防范可能出现的各种越界访问问题。 - 另外一个重要改进之处就在于一旦发现任何违反约束条件的情形——无论是由于提供了错误尺寸还是尝试超出界限书写等都会立刻中断执行流程并将控制权交回调用端同时设置相应的错误码[^4]。 - **返回值含义的不同解释方式** - 对于成功的调用而言,两种方法都倾向于告知实际完成打印操作的数量或者是预期需要的空间数目; - 然而在失败状况下则有所区分:前者依旧遵循惯例给出理论上的需求长度;后者更多时候会选择直接报错(-1),并且伴随具体的错误指示信息存放在全局变量errno当中以便后续查询分析[^5]。 ```c #include <stdio.h> #include <stdarg.h> // 使用 vsnprintf 示例 int example_vsnprintf(){ char buf[10]; va_list args; int ret; va_start(args, "%s"); ret = vsnprintf(buf, sizeof(buf), "This is a long string that will be truncated.", args); // 输出会被截断 va_end(args); if(ret >= (int)sizeof(buf)){ printf("Buffer too small! Required at least %d bytes but only had %lu.\n",ret,sizeof(buf)); } else{ puts(buf); } return 0; } // 使用 vsnprintf_s 示例 (Microsoft 特定) #ifdef _MSC_VER #include <sal.h> #include <strsafe.h> int example_vsnprintf_s(){ char buf[10]; va_list args; errno_t err; va_start(args,"%s"); err=vsnprintf_s(buf,_countof(buf),_TRUNCATE,"Another very lengthy message which won't fit into our tiny buffer either...",args);// 应该触发错误处理逻辑 va_end(args); if(err!=0){ perror("An error occurred while trying to safely format the given input."); } else{ fputs(buf,stdout); } return 0; } #endif ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值