sprintf_s与_snprintf与_snprintf_s

MSDN页面分别如下:

spirntf_s:

http://msdn.microsoft.com/zh-cn/library/ce3zzk1k%28VS.80%29.aspx

_snprintf:

http://msdn.microsoft.com/zh-cn/library/2ts7cx93%28v=VS.90%29.aspx

_snprintf_s:

http://msdn.microsoft.com/zh-cn/library/f30dzcf6.aspx

三个页面都有自己的例子。。其中后2个的例子比较多内容一些。

 

为免将来页面失效:

int sprintf_s(
char *buffer,
size_t sizeOfBuffer,
const char *format [,
argument] ...

);

template <size_t size>
int sprintf_s(
char (&buffer)[size],
const char *format [,
argument] ...

); // C++ only

int _snprintf(
char *buffer,
size_t count,
const char *format [,
argument] ...

);

int _snprintf(
char (&buffer)[size],
size_t count,
const char *format [,
argument] ...

); // C++ only

int _snprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format [,
argument] ...

);

int _snprintf_s(
char (&buffer)[size],
size_t count,
const char *format [,
argument] ...

); // C++ only

 

呼呼。。内容还挺多。

 

 

 

这里比较引人注目的是,_snprintf_s为什么在sizeOfBuffer的基础上,还要多加一个count?

count似乎是用来控制理想的宽度的。

如果得到的字符串超过了count,于是会被截断到count的长度后面再加一个null-teminate

当然,更高优先级的应该是sizeOfBuffer,必须不超过这个大小。这个就说到点子上了。

 

如果应该输出的字符串的大小已经达到了sizeOfBuffer,那么就溢出了。溢出的情况下,sprintf_s函数把这当做一个错误,会把buffer缓冲区置为一个空字符串""。

而_snprintf_s的好处就是,有了count参数,输出的字符串就算超过缓冲区长度,仍然会有输出,输出字符串被截断到count大小,在这个大小的字符串后面加null-teminate。

 

当然,如果count被设置成和sizeOfBuffer同样大,或者不合理的更大,那么这个count参数就失去了意义。

这时候,如果输出字符串将要达到或者超过sizeOfBuffer,一样导致一个错误,输出缓冲区被置为空字符串。

因此,如果希望缓冲区被尽量利用,可以把count参数置为_TRUNCATE,这样的情况下,实际上效果相当于是将count设置为sizeOfBuffer - 1。

 

 

至于C语言环境下,sprintf_s与_snprintf的对比:

注意到,_snprintf的参数用的是count,而sprintf_s的参数用的是sizeOfBuffer。这很能说明问题。

看下对_snprintf的说明:

Let len be the length of the formatted data string (not including the terminating null). len and count are in bytes for _snprintf, wide characters for _snwprintf.

If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned.

If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned.

If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned.

 

也就是说,_snprintf的count参数明明白白的就是一个count。

如果输出字符串刚好达到count,由于期待的最大长度就是count,那么输出字符串肯定要完整,不能截断。

但是假如字符串缓冲区的大小其实就是count,这怎么办?MS VCRT的设计者认为,在这种情况下应该把输出字符串的长度告知调用者,让调用者来决定是否自己添加null-teminate。

换句话说,调用_snprintf时要注意了,必须检查_snprintf的返回值,如果返回值不是正数,那么还得注意你的字符串缓冲区并不是null-teminate结尾的。

 

总结来说,sprintf_s在缓冲区不够大时会失败,失败时缓冲区中是一个空字符串。

_snprintf不会失败,但是必须注意如果缓冲区不够大,缓冲区的内容将不是null-teminate的,必须自己注意字符串的结束。

_snprintf_s结合了2者的优点,只要count参数设置合理,函数就不会因缓冲区不够而失败。

 

但是观察_snprintf_s的说明,有一个很有趣的内容。

这3族函数中,有失败情况的2个函数sprintf_s和_snprintf_s中,(再次强调,我这里的失败的意思是,调用后缓冲区里是一个空字符串),_set_invalid_parameter_handler设置的错误处理器,在失败的情况下会被调用。

 

而截断的情况下,错误处理器并不会被调用。

 

VC的库开发者总是提供一些怪怪的东西。无论如何,让代码更加安全总是符合大家的总体期望的。

另外补充一下,查阅这些字符串安全函数的资料的时候要注意,

对微软来说,凡是限制字符串复制长度的函数,这些设计者仍然认为是不安全的,因为逻辑上来说,

这些长度参数只是限制了源字符串被复制的长度,而不是目标缓冲区的长度。

也就是说,微软的这些设计者认为,安全的方式其实是依赖C++的机制,辨认出目标缓冲区的真正大小,以此实现安全的复制。

转载于:https://www.cnblogs.com/yangxx-1990/p/4877111.html

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

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

相关文章

git ssh配置文件 服务器_git登录ssh服务器

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":6,"count":6}]},"card":[{"des":"云服务器 ECS(Elastic Compute Service)是一…

怎么用计算机打分数,电脑excel中分数怎么打出来(图解excel分数输入法)

在日常工作中&#xff0c;我们经常需要在excel中输入分数&#xff0c;默认情况下&#xff0c;当我们直接输入分数&#xff0c;比如输入“9/16” 回车后&#xff0c;会发现系统显示的却是日期数据&#xff0c;如下图所示&#xff0c;那么分数该怎么输入呢&#xff1f;今天就来和…

python终止线程_Python里怎么终止一个线程

Python用sleep停止一个线程的运行&#xff0c;而不影响主线程的运行&#xff0c;案例代码如下&#xff1a; from threading import *import timeclass MyThread(Thread): def run (self): self.ifdo True; while self.ifdo: print I am running... time.sleep(2) def stop (se…

C#中的多线程

1简介及概念 C# 支持通过多线程并行执行代码&#xff0c;线程有其独立的执行路径&#xff0c;能够与其它线程同时执行。 一个 C# 客户端程序&#xff08;Console 命令行、WPF 以及 Windows Forms&#xff09;开始于一个单线程&#xff0c;这个线程&#xff08;也称为“主线程”…

word 7桌面上的计算机图标是,怎么设置win7系统桌面图标都变成word图标的处理办法...

随着电脑的使用率越来越高&#xff0c;我们有时候可能会遇到win7系统桌面图标都变成word图标问题&#xff0c;如果我们遇到了win7系统桌面图标都变成word图标的问题&#xff0c;要怎么处理win7系统桌面图标都变成word图标呢&#xff1f;我们只用  双击打开桌面上的计算机文件…

edge浏览器什么相当于ie的中低_Microsoft Edge浏览器

Microsoft Edge浏览器是微软与Win10同步推出的一款新版浏览器。Microsoft Edge浏览器功能很全面&#xff0c;不仅内置微软Contana&#xff0c;可以为用户带来更多人性化的服务&#xff0c;而且Microsoft Edge浏览器还有着支持插件扩展、网页阅读注释等特色功能&#xff0c;为用…

python3文件的编码类型是什么_python3.x - 怎么查看某个文件的编码方式?python

问 题 python的确很赞&#xff0c;但是编码这个问题真的太尿性了。。。 现在我有一个文件&#xff0c;不论他的编码方式是什么&#xff0c;我都想把它转化成utf-8的格式。我的想法是先读取文件内容&#xff0c;保存到data变量中去&#xff0c;然后再以utf-8的格式写入文件。 但…

STL中 map 和 multimap

1. 所在头文件<map>. 命名空间std, 声明如下: 1 namespace std{2 template <class Key,class T,3 class Compare less<Key>,4 class Allocator allocator<pair<const Key,T> > >5 class map;6 templa…

你每隔多久使用计算机上网查找资料英文,牛津英语8B Unit3导学案

43. Each of the students should ___________(treat) equally[平等地] by our teachers.44. ---When _______ the Museum of London ______(build), do you know? ---Sorry, I‘ve no idea.45.This picture ___________ (paint) by Millie yesterday.46. These photos ______…

python源码剖析_Python源码剖析 - 对象初探

01 前言 对象是 python 中最核心的一个概念&#xff0c;在python的世界中&#xff0c;一切都是对象&#xff0c;整数、字符串、甚至类型、整数类型、字符串类型&#xff0c;都是对象。 02 什么是PyObject Python 中凡事皆对象&#xff0c;而其中 PyObject 又是所有对象的基础&a…

html点线面制作,利用HTML5绘制点线面组成的3D图形的示例

玩Canvas玩了有两三个礼拜了&#xff0c;平面的东西玩来玩去也就那样&#xff0c;所以就开始折腾3D了。因为Canvas画布终究还是平面的&#xff0c;所以要有3D就得抽象出一个Z轴。然后再把3D坐标转换成2D坐标&#xff0c;画到画布上&#xff0c;再通过旋转等变换效果来产生3D感。…

javapanel根据内部组件_[译]避免在unmounted组件上调用setState

[译]避免在unmounted组件上调用setState原文 : https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmounted-component很多人在开发 React 的过程中&#xff0c;会遇到下面这些警告。github上很多issue都和这些警告相关。因此&#xff0c;我想在这篇文章里…

如何写一个脚本语言_零基础小白如何学会写文案?文案写作技巧之一:如何写一个吸引读者的文案开头...

我文笔不好怎样才能够写出优质的文案&#xff1f;很多人都有这个疑问&#xff0c;包括我自己在学习新媒体运营之前&#xff0c;这也是我最大的困惑。现在是内容为王的时代&#xff0c;你的文章质量决定了你的KPI。后来我学习了文章的写作结构和技巧后&#xff0c;就能够写出一篇…

Extjs之RowNumberer

Ext.grid.RowNumberer,Ext.grid.PageRowNumberer 在一个数据表格中,一般都会加一个行号,在ExtJs中,要实现行号这一效果,只需要一句代码: new Ext.grid.RowNumberer() 举个例子,代码如下: var colModel new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),{ header: "…

计算机硬件的维护知识,电脑放了一年开不了机 电脑硬件维护常识要点有哪些...

随着经济的发展&#xff0c;人们走到哪里都是拿着手机&#xff0c;对于家里已有电脑的&#xff0c;完全不会去用下&#xff0c;很多人都觉得手机更加方便&#xff0c;但长时间不用电脑就会导致电脑当中的一些设备出现问题&#xff0c;都知道电脑它主要就会由一些硬件与软件进行…

发那科pmc地址分配_一台全新的FANUC数控机床,请简述有挡块回参功能的实现步骤?包括PMC的I/O分配、具体参数设定、梯形图程序...

展开全部挡块回636f70793231313335323631343130323136353331333433623063参功能的实现步骤由x地址决定的&#xff1a;1、打到回零的选项,动轴回零。2、当挡块被轴台压到的时候就减速了,挡块被压的时候PMC的X地址有一个会变成0。PMC的I/O分配&#xff1a;早期的I/O板用于数控系统…

计算机学院寝室文明风景线活动,小猿关注 | 营造良好学风 打造和谐宿舍 ——计算机学院开展学风主题教育暨文明宿舍评选活动...

原标题&#xff1a;小猿关注 | 营造良好学风 打造和谐宿舍 ——计算机学院开展学风主题教育暨文明宿舍评选活动计算机学院记者团讯(通讯员 苏婉静 编辑 王鸿宇)12月15日晚&#xff0c;计算机学院于九号楼9201教室开展“ 营造良好学风&#xff0c;打造和谐宿舍”主题教育活动&am…

c++ 结构体初始化_STM32入门系列-使用库函数点亮LED,LED初始化函数

要点亮LED&#xff0c;需要完成LED的驱动&#xff0c; 在工程模板上新建一个led.c和led.h文件&#xff0c;将其存放在led文件夹内。这两个文件需要我们自己编写。 通常xxx.c文件用于存放编写的驱动程序&#xff0c;xxx.h文件用于存放xxx.c内的stm32头文件、管脚定义、全局变量声…

swift-UITextfield控件的基本属性设置

//1.初始化UITextField let userNameUITextField(frame: CGRectMake(0, 100, 100, 100)); //2.将文本框userName添加到当前视图中 self.view.addSubview(userName); //3.文本框默认显示文字 userName.placeholder"请输入手机号"; //4.设置字体大小 userName.fontUIFo…

js生日计算年龄_JS根据生日算年龄的方法

本文实例讲述了JS根据生日算年龄的方法。分享给大家供大家参考。具体实现方法如下&#xff1a;function parseDate(str){if(str.match(/^\d{4}[\-\/\s]\d{1,2}[\-\/\s]\d{1,2}$/)){return new Date(str.replace(/[\-\/\s]/i,/));}else if(str.match(/^\d{8}$/)){return new Dat…