snprintf 返回值陷阱 重新封装

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

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

    int snprintf(char *str, int n, char * format [, argument, ...]);
  • str为要写入的目标字符串;
  • n为能写入的字符的最大数目,超过n会被截断,包括'\0'符,所以能最大写入的其实是n-1个字符;
  • format为格式化字符串,使用方式与printf()函数相同;
  • argument为变量,可为多个,取决于format,这里的使用方式与printf相同。
  • 成功则返回参数str 字符串长度(不包括“\0”),失败则返回-1,错误原因存于errno 中。

snprintf()可以认为是sprintf()的升级版,比sprintf()多了一个参数,可以控制要写入的字符串的长度,更加安全,不会造成str的溢出。

不过snprintf也不是尽善尽美的,也有陷阱,当要写入的argument的长度大于str的长度时,返回值不是str的长度,而是argument的长度

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int len;
    char str[5];
    len = snprintf(str, sizeof(str), "%s", "ABCDEFGH");
    printf("str:%s, len:%d.\n", str, len);

    return 0;
}

输出结果:

str:ABCD, len:8.

返回的长度是8而不是4,不注意的话,下边的使用可能有问题。所以,使用后,下边最好再判断一下len的长度是否超过了size。
其实可以自己封装一个my_snprintf的

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

int my_snprintf(char *dst, int size, char *fmt, ...)
{
    int len;
    va_list argp;
    va_start(argp, fmt);
    len = vsnprintf(dst, size, fmt, argp);
    len = len > size - 1 ? size - 1 : len;
    va_end(argp);
    
    return len;
}

int main(void)
{
    char str[8];
    int len;
    
    len = my_snprintf(str, sizeof(str), "A:%d:%s", 1, "ABCDEFGH");
    printf("str:%s, len:%d\n", str, len);

    return 0;
}

输出:

str:A:1:ABC, len:7
目录
相关文章
|
缓存 网络协议 数据安全/隐私保护
[运维笔记] - (命令).Windows server常用网络相关命令总结
[运维笔记] - (命令).Windows server常用网络相关命令总结
691 0
|
SQL 数据可视化 Java
DBeaver数据库可视化工具
DBeaver数据库可视化工具
646 3
|
算法
【MATLAB】语音信号识别与处理:高斯加权移动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:高斯加权移动平均滤波算法去噪及谱相减算法呈现频谱
498 0
|
分布式计算 关系型数据库 BI
加速查询MaxCompute再对接FBI(帆软)的完整链路来啦!
本文旨在分享使用交互式分析查询MaxCompute数据,再对接FBI的完整链路,快速搭建大数据生态完整链路。
4673 0
|
6月前
|
存储 Unix Shell
Shell 输出命令完全指南:echo 与 printf 的深度剖析
本文深入解析了 Shell 编程中 `echo` 和 `printf` 两个核心输出命令的用法与区别。`echo` 简单易用,适合基础输出;`printf` 功能强大,支持复杂格式化。文章从语法、转义序列、高级技巧到实际应用场景(如日志记录、进度显示)逐一讲解,并对比两者的性能与适用场景,帮助开发者根据需求灵活选择。最后通过进阶技巧和常见问题解答,进一步提升对两者的掌握程度。
302 1
|
11月前
|
编解码 缓存 算法
视频帧里的I帧、P帧、B帧是什么?
I帧、P帧、B帧是视频编码中的基本概念。I帧是帧内编码帧,无需参考其他帧即可解码;P帧是前向预测编码帧,基于前一帧解码;B帧是双向预测编码帧,基于前后帧解码。IDR帧是一种特殊的I帧,用于即时解码刷新,防止错误传播。GOP(Group of Pictures)是一组连续的画面,第一个帧为I帧,gop_size设置越大,画质越好,但解码延迟增加。OpenGOP允许GOP间的帧依赖,而ClosedGOP则不允许。DTS(解码时间戳)和PTS(显示时间戳)分别用于解码和显示时间控制。
|
9月前
|
设计模式 存储 关系型数据库
「全网最细 + 实战源码案例」设计模式——六大设计原则
本文介绍了面向对象设计中的六大原则,旨在提高软件系统的可维护性、可复用性和可拓展性。这些原则包括:开闭原则(OCP)、里氏代换原则(LSP)、依赖倒转原则(DIP)、接口隔离原则(ISP)、迪米特法则(LoD)和合成复用原则(CARP)。每项原则通过具体示例展示了如何通过抽象、多态、组合等方式降低耦合度,增强系统的灵活性与稳定性,从而提升开发效率并降低成本。
199 10
|
12月前
|
编解码 监控 API
直播源怎么调用api接口
调用直播源的API接口涉及开通服务、添加域名、获取API密钥、调用API接口、生成推流和拉流地址、配置直播源、开始直播、监控管理及停止直播等步骤。不同云服务平台的具体操作略有差异,但整体流程简单易懂。
|
算法 安全 数据中心
BGP MD5认证的原理与实现
【7月更文挑战第15天】
259 3
BGP MD5认证的原理与实现
|
开发者
CMake 命令行使用指南:创建构建目录与编译项目
CMake 命令行使用指南:创建构建目录与编译项目
695 0