snprintf 函数用法心得

2023-05-16

前人挖坑,后人种树。

不能对同一段内存(同一个buf) 或是两个重叠的内存使用snprintf,换句等方面说,在使用snprintf 时,就确保内存不重叠。


先来看看一段问题代码的执行结果。 代码是前人所作,从工程Copy出来后稍做修改,用途是对输入字符串进行排序,输入为0~7的任意组合。

#include <stdio.h>
#include <string.h>

void main()
{
    char week[32] = "0,1,2,6,5";
    char new_week[32] = {0};
    int i = 0;
    char *weekday[] ={"0","1","2","3","4","5","6","7"};
    int n = 0;
    for(i = 0; i < 8; i++)
    {
       if(strstr(week, weekday[i]))
       {
         snprintf(new_week,sizeof(new_week),"%s%s,", new_week, weekday[i]);
         n += 2;
       }
    }
    if (new_week[n - 1] == ',')
        new_week[n - 1] = 0;

     printf("week: %s\t; new_week: %s\n", week, new_week);
}




编译如下:



1) 在MIPS(BRCM6838 CPU)平台下运行如下: 


结果如预期。


2) 在笔者的主机上运行如下: 


并不是所期望的结果, new_weeek 只有最后一位(排序后的)。


3) 在ARM平台下运行如下:



不能对同一段内存(同一个buf) 或是两个重叠的内存使用snprintf,换句等方面说,在使用snprintf 时,就确保内存不重叠。


总结:

我们发现在MIPS平台上,程序运行结果是我们所期望的结果。但是是Intel 和ARM平台上, 程序并非按期望的结果运行。


通过研究发现,不同构架所链接的库文件不同,而不同的库文件对sprintf的实现不同。 在MIPS平台上所UClibc, 在ARM平台上使用的库为 glibc。两者的实现不同。

在glibc中,对snprintf为实现,函数调用关系如下:


 

snprintf (char *s, size_t maxlen, const char *fmt, ...)
{
	...
	done = __nldbl_vsnprintf (s, maxlen, fmt, arg);
	...
}
	
	__nldbl_vsnprintf (char *string, size_t maxlen, const char *fmt, va_list ap)
	{
		...
		res = _IO_vsnprintf (string, maxlen, fmt, ap);
		...
	}

		_IO_vsnprintf (string, maxlen, format, args)
		{
			...
			string[0] = '\0';
			...
		}


在 _IO_vsnprintf 函数的实现中 中有一行代码为:

 string[0] = '\0';

for(i = 0; i < 8; i++) {
    ...
    
    n += snprintf(new_week + n, sizeof(new_week), "%s,", weekday[i]);
    // snprintf(new_week,sizeof(new_week),"%s%s,", new_week, weekday[i]);  // TODO: 而不是这样

    ...
}

用来首先清空目标buf的内容,所以在就出现了如前所示的在主机的ARM平台的运行结果,结果只取得了最后一位。

本文的中的问题代码对的snprintf函数的用法是有误的,即下面的用法是不正确的。

snprintf(new_week,sizeof(new_week),"%s%s,", new_week, weekday[i]);


结论:

不能对同一段内存(同一个buf) 或是两个重叠的内存使用snprintf,换句等方面说,在使用snprintf 时,就确保内存不重叠,否则结果不可预期。


补充:

基于上面的结论有朋友提出这样的问题:那么如何在调用前确定src与dst不重叠。

其实,准确地说,对于 snprintf, 1) 就不能有出现重叠的情况,2) src与dst更不能使用同一段内存。

对于1),snprintf 原型如下,其中第二个参数就是用来确保内存不重叠的,dst所申请内存的大小必须大于或等于(一般取等于)第二个参数maxlen的值。

snprintf (char *s, size_t maxlen, const char *fmt, ...)

对于2) 在本例中,src与dst使用同一段内存,其初衷是为了在原有内存(字符串)追加新的内容(通过把int转化为char),那么对于这种情况的正确用法如下。

for(i = 0; i < 8; i++) {
    ...
    
    n += snprintf(new_week + n, sizeof(new_week), "%s,", weekday[i]);
    // snprintf(new_week,sizeof(new_week),"%s%s,", new_week, weekday[i]);  // TODO: 而不是这样

    ...
}



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

snprintf 函数用法心得 的相关文章

  • PID控制

    目录 1 基本情况1 1 位置式PID1 2 增量式PID1 3 PID控制适用系统 2 PID三个量的含义解析2 1 P xff1a 比例2 2 I xff1a 积分2 3 D xff1a 微分2 4 PID xff1a 三者的关系 3
  • VSCode Python运行环境配置

    背景 创建了一个python的虚拟运行环境 xff0c 比如说tensoflow xff0c 想在VS Code下运行调试 步骤 参考说明 xff1a https blog 51cto com u 15127658 2783413 xff0
  • Tomcat中文乱码解决方案【亲测有效】

    场景一 xff1a SpringBoot项目 xff0c 在IDEA中启动 xff0c 访问接口 xff0c 无乱码 场景二 xff1a SpringBoot项目 xff0c 打成war包 xff0c 发到本地tomcat下 xff0c 启
  • 【Python】How to center an image in canvas Python Tkinter

    https www tutorialspoint com how to center an image in canvas python tkinter https www tutorialspoint com how to insert
  • [python]使用pyinstaller打包带界面的Pytorch程序的多个问题

    1 opencv兼容性问题 1 1 现象 打包为一个exe完成后 xff0c 在执行exe时 xff0c 报错 xff1a ImportError ERROR recursion is detected during loading of
  • VS2019下载与安装

    下载 xff0c 这里有一个说明 xff0c 下载说明 不再赘述 补充一下 xff0c 上面的地址中 xff0c 是VS2022的 xff0c 应该放的最新的 老的版本在这里下载 xff1a https visualstudio micro
  • Ubuntu下QtCreator的C++工程调用python

    目录 1 概述1 1 参考1 2 库引用1 3 初始与善后 2 函数调用3 类调用4 参数传递4 1 传递数值类型4 2 传递字符串4 3 传递bool4 4传递图片 5 解析放回的参数5 1 调用方法5 2 数值解析5 3 字符串解析5
  • Ubuntu的QTCreator中c++调用opencv方法

    注意 xff1a 这里用的是opencv 4 0以上版本 如果是4 0下的版本 xff0c 配置不同 xff0c 4 0在这个头文件之类的有变化 QTCreator下创建工程 xff0c 在工程文件 pro中增加配置 xff1a span
  • Ubuntu Qtcreator c++调用python报错

    调用时候 xff0c 报错 xff1a modpython 13107 Gtk ERROR 20 32 18 627 GTK 43 2 x symbols detected Using GTK 43 2 x and GTK 43 3 in
  • [Ubuntu, Ajax Nx]C++调用python报from import错误

    1 现象描述 c 43 43 调用python程序 调用的main函数 xff0c 该main函数中有如下代码 xff1a span class token keyword from span matching span class tok
  • Linux下c++串口编程

    1 NX串口管理 参见https blog csdn net weixin 42447868 article details 109051005 spm 61 1001 2014 3001 5506 2 串口权限管理 2 1 串口权限 xf
  • Jetson Nx 串口接收数据丢失首字节问题

    1 问题描述 I write a uart program using c 43 43 on Jetson Nx Jetpack 4 6 1 Ubuntu version 18 04 LTS to communicate with a PC
  • Linux下的一些基础功能

    1 关于命令行输出到文件 xff1a https www iplayio cn post 6296803 2 kz 64 JetsonNx ls l dev ttyS dev ttyUSB dev ttyTHS dev ttyCUDA ls
  • SpringBoot ☞ logback日志配置【屏蔽第三包中日志输出】

    一 项目配置文件如下 二 场景 项目启动时 xff0c 控制台无缘无故输出很多error级别的日志 xff0c 让人看着很不舒服 xff0c 断点调试 43 跟踪 xff0c 发现原来是第三方jar包里设置了日志输出 xff0c 如下 xf
  • 通过Xshell操作Jetson Nx

    1 Jetson Nx Nx留有Uart2 口 xff0c 便于使用xshell等进行操作 串口有三根线 链接后使用 2 XShell 软件 2 1 XShell软件介绍 XShell 软件是一个Windows上运行的终端模拟器 xff0c
  • Nx C++程序使用spdlog库进行日志存储

    1 spdlog简介 spdlog是一个开源的日志库 xff0c 在github上有 代码见这里 xff0c 文档这里 C 43 43 语言的 xff0c 支持Linux windows等系统 csdn上也有许多介绍 xff0c 这里列举两
  • C++下的Boost库

    1 介绍 xff08 引子网络 xff09 Boost库是为C 43 43 语言标准库提供扩展的一些C 43 43 程序库的总称 xff0c 由Boost社区组织开发 维护 Boost库可以与C 43 43 标准库完美共同工作 xff0c
  • Opencv之边界跟踪

    问题描述 一般是将二值化后的图像进行边界的提取 需要说明的是这个提取不是简单的找到边界 xff0c 而是按照顺序的找出来 即边界上的点是按照邻接关系依次给出 相关算法 xff08 1 xff09 这里解释 xff1a https blog
  • OpenCV之滤波

    图像滤波 xff0c 指在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制 xff0c 是图像预处理中不可缺少的操作 xff0c 其处理效果的好坏将直接影响后续图像处理和分析的准确性 这里有个概述 xff0c 很好的 xff1a Ope
  • C++文件读写

    这个不错 xff1a C 43 43 文件读写详解 xff08 ofstream ifstream fstream xff09 C 43 43 文件读写详解 xff08 ofstream ifstream fstream xff09 c 4

随机推荐

  • python及其工具

    目录 1 conda xff1a 包管理器2 Anoconda xff1a 开源的包 环境管理器3 labelme4 tensorflow5 cuda和cudnn6 使用yml文件创建环境并安装文件6 1 yml文件由来6 2 如何获得ym
  • C++之文件操作移动、复制、重命名

    1 C 43 43 笔记之CopyFile和MoveFile的使用 2 删除和重命名 include lt fstream gt include lt windows h gt 与opencv的命名空间CV有冲突 xff0c 不能在一个文件
  • (转)C#数字转固定长度的字符串

    转 C 数字转固定长度的字符串
  • 进程监视工具

    Process Monitor 搜索能下到 xff0c 记下 xff0c 以后用 Process Monitor分析某个应用行为 Process Monitor 系统进程监视器 介绍教程 Using Process Monitor 帮助文档
  • UML建模工具Enterprise Architect(EA) -- 安装及简单使用

    目录 一 什么是EA xff1f 二 安装EA 三 为什么要学会用EA 四 创建EA工程 五 创建类视图 xff0c 构建类和接口 六 选中模型目录 xff0c 自动检出Java代码 七 构建内部类 八 趁热打铁 xff0c 构建数据表视图
  • SVN目录结构与分支等

    TortoiseSVN打分支 合并分支 切换分支 SVN创建分支 合并分支 切换分支
  • WPF上下标

    这里有个介绍的文章 xff1a 定义显示的上标和下标 里面介绍了三种方法 我之前有的是这个方法 xff1a Typography Variants 61 Superscript xff0c 如下所示 xff1a lt TextBlock g
  • [WPF] HamburgerMenu

    有两个库支持的 xff1a Metro App库中的 VS自己的控件 xff1a https docs microsoft com zh cn windows communitytoolkit archive hamburgermenu
  • 面积误差三种计算表达的比较

    引自 xff1a 面积误差三种计算表达的比较 有三种理论 xff0c 最基本的经典的 xff0c 引用一个吧 xff1a 网上有个题目 xff0c 求桌面面积的测量结果 桌面为矩形 用米尺测量 xff0c 长L为100 0 cm xff0c
  • 【转】WPF:Canvas中元素的定位

    概述 xff1a Canvas中的元素的大小和位置都是相对于Canvas容器的 xff0c 他的左上角为原点 xff0c 长度也是相对于他的 WPF xff1a Canvas中元素的定位 https blog csdn net chz cs
  • 【转】C#中计时

    一般可以用Environment TickCount xff0c 但是25天后会翻转 有很多 xff0c 见下面两个转的 C 中精确计时的一点收获 https www cnblogs com jintianhu archive 2010 0
  • 利用python分析微信聊天记录

    文章目录 前言一 任务分析二 工具三 步骤1 数据获取获取DB计算密码导出数据库 2 数据清洗 xff08 具体方法以后补充 xff09 3 数据分析 前言 昨天跟女朋友讨论谁给对方发的消息比较多 xff0c 两人各执一词 xff0c 事实
  • C++学习之模板

    文章目录 xff1a 一 模板 二 函数模板 三 类模板 一 模板 模板 也称泛型编程 泛型编程 xff1a 编写与类型无关的通用代码 xff0c 是代码复用的一种手段 模板是泛型编程的基础 在这之前我们可以利用C 43 43 的函数重载来
  • ROS2 创建python包

    1 创建python包 ros2 pkg create build type ament python span class token string 39 demo 39 span dependencies rclpy 以上指令为创建一个
  • Springboot集成SpringSecurity过程中遇到的问题

    Spring Security 开发文档 xff1a https www springcloud cc spring security zhcn html 一 配置的免登录访问接口不生效 span class token annotatio
  • 在sublime text3中配置c/c++运行环境

    在参考网上诸多大神配置sublime text3后 xff0c 自己也想写一篇有关在sublime中配置c c 43 43 的运行环境的文章 xff0c 顺便总结一下 安装sublime text3 xff1a 下载地址 xff08 官方地
  • STM32CubeMX 新建工程详细步骤

    STM32CubeMX 新建工程详细步骤 1 MPU CPU选择step1 打开CubeMX 软件 xff0c 在主页面上 点击如下按钮 xff0c 进入芯片选择界面step2 在Part Number Search 栏搜索我们需要用到的芯
  • macOS 10.11、macOS 10.12、macOS 10.13、macOS 10.14、macOS 10.15 制作可用于虚拟机安装的 CDR/ISO 系统镜像指导教程

    开篇说明 xff1a 不论是用 UltraISO xff0c 或者是用 MacOS 系统中的 磁盘工具 的格式转换功能进行 原版 DMG 61 61 gt CDR ISO 转换出来的 CDR ISO 文件只是进行了格式 xff08 容器 x
  • win10安装wsl2

    一 环境准备 1 确保bios开启虚拟化支持 各品牌主板进入bios的方式可百度或看主板说明书 2 查看当前win10版本是不是最新版 xff0c 如果不是则升级到最新版 查看当前版本 xff0c win 43 r打开运行窗口输入 34 w
  • snprintf 函数用法心得

    前人挖坑 xff0c 后人种树 不能对同一段内存 xff08 同一个buf 或是两个重叠的内存使用snprintf xff0c 换句等方面说 xff0c 在使用snprintf 时 xff0c 就确保内存不重叠 先来看看一段问题代码的执行结