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

sprintf_s与_snprintf与_snprintf_s相关推荐

  1. sprintf_s、_snprintf与_snprintf_s

    一.函数原型 1.sprintf_s int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format[,argument].. ...

  2. sprintf, snprintf, _snprintf, sprintf_s 等的区别

    先放结论 1.在支持snpritf的编译器 ,只使用int snprintf( char *buffer, size_t count, const char *format [, argument] ...

  3. _snprintf_s与_snprintf

    VS2010测试百度百科给出的例子: char a[16]; size_t i; _snprintf_s 会自动自动截断,保留最大需要拷贝的字符串长度cout(即第二个参数) _snprintf 不会 ...

  4. sprintf、vsprintf、sprintf_s、vsprintf_s、_snprintf、_vsnprintf、snprintf、vsnprintf 函数辨析

    看了题目中的几个函数名是不是有点头晕?为了防止以后总在这样的细节里纠缠不清,今天我们就来好好地辨析一下这几个函数的异同. 实验环境: Windows下使用VS2017 Linux下使用gcc4.9.4 ...

  5. linux下snprintf用法,关于snprintf,_snprintf,_snprintf_s操作

    一.snprintf与snprintf_s的区别 众所周知,sprintf不能检查目标字符串的长度,可能造成众多安全问题,所以都会推荐使用snprintf. snprintf函数在C++11之前 并不 ...

  6. Qt sprintf_s函数格式化字符串出错

    Qt sprintf_s函数格式化字符串出错 问题的出现: 我在VS上用c C++写的跨平台的函数 移植到Qt 上面 出现sprintf_s 函数格式化出错. 开始以为是编码问题  反复查找Qt乱码问 ...

  7. “_snprintf”: 不是“std”的成员

    使用c++ json库时报错: https://github.com/nlohmann/json.git "_snprintf": 不是"std"的成员 原文: ...

  8. sprintf_s的使用

    int sprintf_s(char *restrict buffer, rsize_t bufsz,               const char *restrict format, ...); ...

  9. [C/C++]记录:使用sprintf_s时第二个参数不严格计算导致栈损坏

    (1)使用sprintf_s时第二个参数不严格计算导致栈损坏的情况 这段代码之前便是函数的定义变量的部分. 此处没有严格计算第一个参数指向的字符串的可用长度. 查看局部变量,发现在函数开头初始化为0的 ...

最新文章

  1. 纯css实现responsive list -- 魔力calc
  2. php7实践指南图书手册
  3. wincc 关闭弹出窗口C语言,退出WINCC操作画面时弹出对话框要求输入用户名和密码-工业支持中心-西门子中国...
  4. Linux GDB常用命令一栏
  5. 通过一个例子学习Kubernetes里的PersistentVolumeClaim的用法
  6. Windows下的ssh姐妹花 Xshell 和 Xftp
  7. Struts 2.x No result defined for action 异常
  8. (转)浏览器兼容的JS写法总结
  9. centos7安装mysql允许远程连接_CentOS7安装Mysql并配置远程访问
  10. python---subplot函数
  11. 通过shell脚本防止端口扫描
  12. windows反馈中心服务器,Windows 管理中心入门
  13. mac安装telnet命令
  14. 【攻略】舰これ辅助程式介绍-航海日志
  15. 做外贸如何免费申请企业邮箱?
  16. 重磅!中国首家互联网银行联手腾讯、华为各大APP,最高5万额度,疯狂提额100亿!!!...
  17. 机器学习实验二 决策树
  18. [POI2005] SZA-Template
  19. Dcloud安卓离线打包
  20. 英特尔商用客户端焕“芯”,释放数字时代三重生产力

热门文章

  1. nodejs+supertest+mocha 接口测试环境搭建
  2. Java多线程(五) —— 线程并发库之锁机制
  3. 微软MIX11大会第一天主旨以及新产品发布总结
  4. IXMLDOMDocument中的load方法返回值有BUG
  5. 题库 java_java题库
  6. Visual.Assist.X.V10.7.1946的汉化破解补丁
  7. PMP读书笔记(第3章)
  8. Pi network KYC的经验分享
  9. 基于Docker搭建私有镜像仓库
  10. ora--12154 :TNS :could not resolve the connect identifier specified 错误处理