关于sprintf和snprintf的比较

#include <stdio.h>
#include <string.h>typedef unsigned char uchar;#define BUF_SIZE 10						// 缓冲区大小
#define CLEAR_SIZE (BUF_SIZE+2)			// 操作的缓冲区大小, 需要全部重置void printRuler(int len)
{putchar('\n');for(int i = 1; i <= len; i++){printf("%02d ", i);if(i == BUF_SIZE)printf("\t|\t");}putchar('\n');
}void dis(char *buf, int len)
{for(int i = 0; i < len; i++){printf("%02x ", (uchar)buf[i]);if(i == BUF_SIZE - 1)printf("\t|\t");}
//	puts("\n");				// 另起一行输出字符串并换行, 不会接在原来的后面putchar('\n');			// 直接输出字符printf("buf=[%s]\n\n", buf);
}int main()
{char buf[BUF_SIZE];memset(buf, 0xcc, CLEAR_SIZE);dis(buf, CLEAR_SIZE);printRuler(CLEAR_SIZE);printf("-------------------------------------- snprintf\n");memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "12345678");		// 未溢出dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789");		// 未溢出, 刚好填满dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789A");	// 未溢出, 被截断1个字符dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789AB");	// 未溢出, 被截断2个字符dis(buf, CLEAR_SIZE);//printRuler(CLEAR_SIZE);printf("-------------------------------------- sprintf\n");memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "12345678");					// 未溢出dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789");				// 刚刚好dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789A");				// 溢出1个字符dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789AB");				// 溢出2个字符dis(buf, CLEAR_SIZE);return 0;
}/*运行情况:
D:\profile\Desktop\test>make
g++ -o a.exe a.cppD:\profile\Desktop\test>a
cc cc cc cc cc cc cc cc cc cc   |       cc cc
buf=[烫烫烫烫烫烫@]01 02 03 04 05 06 07 08 09 10   |       11 12
-------------------------------------- snprintf
31 32 33 34 35 36 37 38 00 cc   |       cc cc
buf=[12345678]31 32 33 34 35 36 37 38 39 00   |       cc cc
buf=[123456789]31 32 33 34 35 36 37 38 39 00   |       cc cc
buf=[123456789]31 32 33 34 35 36 37 38 39 00   |       cc cc
buf=[123456789]01 02 03 04 05 06 07 08 09 10   |       11 12
-------------------------------------- sprintf
31 32 33 34 35 36 37 38 00 cc   |       cc cc		// 空间有余
buf=[12345678]31 32 33 34 35 36 37 38 39 00   |       cc cc		// 刚好填充満
buf=[123456789]										31 32 33 34 35 36 37 38 39 41   |       00 cc		// 溢出1个字符
buf=[123456789A]31 32 33 34 35 36 37 38 39 41   |       42 00		// 溢出2字符
buf=[123456789AB]结论:1. sprintf和snprintf都会在字符串末尾加上'\0'2. snprintf比sprintf安全,即不会造成缓冲区溢出
*/

以上的测试环境是GNUMake(windows), 和Linux.


===============================================================================

以下的代码测试环境是windows vc6和vc2010

#define _CRT_SECURE_NO_WARNINGS			// 针对vc2010添加#include <stdio.h>
#include <string.h>typedef unsigned char uchar;#ifdef WIN32#define snprintf _snprintf			// windows平台无snprintf, 但是有_snprintf
#endif#define BUF_SIZE 10						// 缓冲区大小
#define CLEAR_SIZE (BUF_SIZE+2)			// 操作的缓冲区大小, 需要全部重置void printRuler(int len)
{putchar('\n');for(int i = 1; i <= len; i++){printf("%02d ", i);if(i == BUF_SIZE)printf("\t|\t");}putchar('\n');
}void dis(char *buf, int len)
{for(int i = 0; i < len; i++){printf("%02x ", (uchar)buf[i]);if(i == BUF_SIZE - 1)printf("\t|\t");}
//	puts("\n");				// 另起一行输出字符串并换行, 不会接在原来的后面putchar('\n');			// 直接输出字符printf("buf=[%s]\n\n", buf);
}int main()
{char buf[BUF_SIZE];memset(buf, 0xcc, CLEAR_SIZE);dis(buf, CLEAR_SIZE);printRuler(CLEAR_SIZE);printf("-------------------------------------- snprintf\n");memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "12345678");		// 未溢出dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789");		// 未溢出, 刚好填满dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789A");	// 未溢出, 被截断1个字符dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);snprintf(buf, BUF_SIZE, "%s", "123456789AB");	// 未溢出, 被截断2个字符dis(buf, CLEAR_SIZE);//printRuler(CLEAR_SIZE);printf("-------------------------------------- sprintf\n");memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "12345678");					// 未溢出dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789");				// 刚刚好dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789A");				// 溢出1个字符dis(buf, CLEAR_SIZE);memset(buf, 0xcc, CLEAR_SIZE);sprintf(buf, "%s", "123456789AB");				// 溢出2个字符dis(buf, CLEAR_SIZE);return 0;
}/*运行情况(vc6/vc2010):cc cc cc cc cc cc cc cc cc cc   |       cc ccbuf=[烫烫烫烫烫烫?]01 02 03 04 05 06 07 08 09 10   |       11 12-------------------------------------- snprintf31 32 33 34 35 36 37 38 00 cc   |       cc cc		// 未溢出时会填充字符串结束符('\0')buf=[12345678]31 32 33 34 35 36 37 38 39 00   |       cc cc		// 未溢出时会填充字符串结束符('\0')buf=[123456789]31 32 33 34 35 36 37 38 39 41   |       cc cc		// 溢出了将不会填充字符串结束符('\0')buf=[123456789A烫?]31 32 33 34 35 36 37 38 39 41   |       cc cc		// 溢出了将不会填充字符串结束符('\0')buf=[123456789A烫?]01 02 03 04 05 06 07 08 09 10   |       11 12-------------------------------------- sprintf31 32 33 34 35 36 37 38 00 cc   |       cc ccbuf=[12345678]31 32 33 34 35 36 37 38 39 00   |       cc ccbuf=[123456789]31 32 33 34 35 36 37 38 39 41   |       00 ccbuf=[123456789A]31 32 33 34 35 36 37 38 39 41   |       42 00buf=[123456789AB]结论:1. windows上无snprintf,但是有_snprintf可以达到同样的功能,但是细节之处略有不同2. 未溢出时,sprintf和snprintf都会在字符串末尾加上'\0';3. 超出缓冲区大小时,_snprintf不会造成溢出,但是不会在缓冲区中添加字符结束符4. sprintf始终会在字符串末尾添加结束符,但是存在缓冲区溢出的情况5. _snprintf比sprintf安全,即不会造成缓冲区溢出6. vc6中对于_snprintf缓冲区溢出时不会出现崩溃信息,但是在vc2010中却会出现
*/



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[react] React的isMounted有什么作用?

[react] React的isMounted有什么作用&#xff1f; (页面执行异步请求&#xff0c;切换页面 &#xff0c;组件卸载 增加isMounted 作为判断) 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 …

鸽巢原理入门

鸽巢原理又叫抽屉原理&#xff0c;百度百科的定义是&#xff1a;桌上有十个苹果&#xff0c;要把这十个苹果放到九个抽屉里&#xff0c;无论怎样放&#xff0c;我们会发现至少会有一个抽屉里面至少放两个苹果。这一现象就是我们所说的“抽屉原理”。 下面有两个入门题目&#x…

javascript笔记:javascript的前世,至于今生嘛地球人都知道了哈

&#xff08;引子&#xff1a;javascript其实是个私生子&#xff09;我在上一篇博文最后说道&#xff0c;想写一篇关于javascript基础语法的文章&#xff0c;原因是我在读很多优秀的javascript源码时候常常被javascript诡异的语法搞的精疲力尽&#xff0c;所以时不时的加固java…

gcc -E 产生预编译后的文件

利用gcc -E选项&#xff0c;可以得到预编译后的文件。这可以得到宏展开后的文件。 先来看看几个相关联的文件吧! #ifndef __DEFS_H__ #define __DEFS_H__#ifdef WIN32#define snprintf _snprintf #endif// Join two variables #define MACRO_JOIN( X, Y ) MACRO_DO_JOIN( X, Y…

[react] 在React中我们怎么做静态类型检测?都有哪些方法可以做到?

[react] 在React中我们怎么做静态类型检测&#xff1f;都有哪些方法可以做到&#xff1f; flow 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

STM32F4 使用STLink 和 EventRecoder 调试运行时间

最近使用STM32F407的DSP库&#xff0c;测试了一下浮点数1024个点的FFT计算时间&#xff0c;采用EventRecoder计时间&#xff0c;记录如下。 1、在Compiler中添加EventRecorder 组件&#xff0c;CMSIS的版本5.4。 2、main.C增加头文件&#xff1a;#include "EventRecorder…

道德经经典解读

老子说&#xff1a;上善若水。水善利万物而不争。 原著实录 《道德经》第8章&#xff1a;上善若水。水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道。居善地&#xff0c;心善渊&#xff0c;与善仁&#xff0c;言善信&#xff0c;政善治&#xff0c;事善能&…

_attribute_((packed))

From: http://blog.csdn.net/wesleyluo/article/details/7565165 _attribute_((packed)) 1. __attribute__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐&#xff0c;是GCC特有的语法。这个功能是跟操作系统没关系&#xff0…

制作centos安装u盘

制作centos安装u盘 格式化 mkfs.vfat /dev/sdb1 制作 dd ifCentOS-7-x86_64-Minimal-1503-01.iso of/dev/sdb # 1. 注意是/dev/sdb 不是/dev/sdb1 # 2. bios中将硬盘设置为AHCI模式 posted on 2015-10-23 11:28 北京涛子 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnb…

[react] 怎么在JSX里属性可以被覆盖吗?覆盖的原则是什么?

[react] 怎么在JSX里属性可以被覆盖吗&#xff1f;覆盖的原则是什么&#xff1f; 会被覆盖&#xff0c;类似Object.assign&#xff0c;后面的覆盖前面的 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨…

Keil5 EventRecorder 的STDOUT输出丢包率较大现象

采用STLINK EventRecorder 对printf进行重定义&#xff0c;在连续发送数据时&#xff0c;存在较大的丢包情况。因此&#xff0c;调试小数据量时可以采用这种方法&#xff0c;大数据量的时候还是直接用UART 进行输出。

使用 C++ 处理 JSON 数据交换格式

From: http://blog.csdn.net/xt_xiaotian/article/details/5648388 使用 C 处理 JSON 数据交换格式 一、摘要 JSON 的全称为&#xff1a;JavaScript Object Notation&#xff0c;顾名思义&#xff0c;JSON 是用于标记 Javascript 对象的&#xff0c;JSON 官方的解释为&#x…

Etherchannel的配置 三层

三层以太网通道 interface FastEthernet0/19 no switchport no ip address channel-protocol lacp channel-group 30 mode active ! interface FastEthernet0/20 no switchport no ip address channel-protocol lacp channel-group 30 mode active interface Port-chan…

[react] immutable的原理是什么

[react] immutable的原理是什么 使用字典树持久化数据结构&#xff0c;更新时可优化对象生成逻辑&#xff0c;降低成本 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面…

CubeMx 生成的FreeRTOS 代码在ARM compiler6 编译__forceinline 报错的解决方法

一、问题 如题&#xff0c;CubeMx 生成的FreeRTOS 代码在ARM compiler6 编译__forceinline 报错的解决方法。 二、解决方法 第一种方法&#xff0c;将编译器换回default compiler version 5。 第二种方法&#xff0c;更换freeRTOS移植源码文件。 将FreeRTOS源码xxx\FreeRTOS…

解决centos KDE命令提示符和文字不紧贴的问题

注意此时cd后面是没有空格的但此时却显示像有空格的一样&#xff0c;要解决这个问题就需要修改PS1 在自己的home的目录下更改.bashrc 例如root就在/root下 PS1"\e[1;32m\u\e[m\e[1;33m\e[m\e[1;35m\h\e[m:\w\$ "转载于:https://www.cnblogs.com/597845634ds/p/490557…

UPS电源远程关机

UPS电源的APC软件是个单机PowerChute Business Edition 的&#xff0c;一个UPS电源上也不是一台服务器&#xff0c;如何在停电的时候把其它服务器也关了&#xff0c;难不成再去买网络版。Windows从xp以上就可以远程关机了&#xff0c;shutdown命令。PowerChute是以系统服务在后…

[react] 什么是React的实例?函数式组件有没有实例?

[react] 什么是React的实例&#xff1f;函数式组件有没有实例&#xff1f; React的实例&#xff1a;通过继承React.Component的类生成 函数式组件没有实例 个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一…

安卓dalvik和art区别

Dalvik模式像是一台折叠自行车&#xff0c;每次骑之前都要组装后才能上路。而ART模式就是一个已经装好的自行车&#xff0c;直接就能上车走人。所以ART模式在效率上肯定是要好于Dalvik。 通过以上这种表格&#xff0c;我们可以直白的看出&#xff0c;全新的ART模式具备用RAM内存…