snprintf返回值陷阱封装

snprintf函数

snprintf()函数用于将格式化的数据写入字符串,其原型为:

int snprintf(char *str, int size, char * format [, argument, ...]);
  • str为要写入的目标字符串;
  • size为能写入的字符的最大数目,超过n会被截断,包括’\0’符,所以能最大写入的其实是size-1个字符;
  • format为格式化字符串,使用方式与printf()函数相同;
  • argument为变量,可为多个,取决于format,这里的使用方式与printf相同。

返回值:

  • 如果格式化后的字符串长度小于等于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;
  • 如果格式化后的字符串长度大于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。

对于snprintf有一个不安全的地方就是它的返回值:当要写入的argument的长度大于str的长度时,返回值不是str的长度,而是argument的长度。

#include <stdio.h>
#include <string.h>
int main(void)
{
        char str[5] = {0};
        int ret_len = 0;
        char* arg = "hello world";

        ret_len = snprintf(str, sizeof(str), "%s", arg);
        printf("str = %s\nret_len = %d\n", str, ret_len);

        return 0;
}

输出结果:

在这里插入图片描述
返回的长度是11而不是4,不注意的话,下边的使用可能有问题。所以我们需要对返回值进行封装。

int my_snprintf(char* buf, int max, char* fmt, ...)
{
    int len;
    va_list argp;
    
    if (buf ==  NULL){
        return -1;
    }

    //用来判断buf长度是否已经用完
    if (max <= 1){
        printf("buf_len not enough\n");
        return -1;
    }

    va_start(argp, fmt);
    len = vsnprintf(buf, max, fmt, argp);

    //用来限定返回值是我们实际写入的字节数
    len = len > max - 1 ? max - 1 : len;
    va_end(argp);

    return len;    
}

这上面用到了可变参数,首先我们需要先了解可变参数的原理。推荐一篇文章讲的挺清楚的,不懂这个可变参数原理的大家可以去下面那个链接去看。
可变参数原理
原看到这篇文章的小伙伴都能搞懂!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值