字符串函数sprintf / sprintf_s 容易出错的地方
其实,用C/C++做开发的童鞋,对sprintf不会陌生,对该函数的一些问题,一直想好好总结下:
如果第2个format(格式)参数中用%指定的后续参数个数与实际参数必须一致,否则可能会出各种问题。所谓一致是严格一致,看几个例子:
1. 参数类型不匹配
如果你用的%d,对应的实参却用double,将得到错误的结果,而且更为严重的是,如果该参数后还有别的参数,将影响后面的参数解析:
char buf[1024];double dV = 123.0;
int iLen = sprintf( buf, "Test: %d, not one %d\n", dV, 1);std::cout << buf;
并不会输出期望的结果:Test: 123, not one 1
我在VS2013下得到的输出是: Test: 0, not one 1079951360
如果我们知道函数调用和参数传递的机理,就会明白,sprintf 期望format参数后接2个int型参数(都是4字节的),但却给了个double参数和一个常数,我们知道double是8字节的,所以double就被分为了2个int,而后面的常数1压根就没用上,所以结果不可能正确。
结果要正确,必须将double参数强转成int:
int iLen = sprintf( buf, "Test: %d, not one %d\n", (int)dV, 1);
2. 参数数目不匹配
format中指定的参数数目与实际的数目不一致时,也得不到正确的结果:
int iLen = sprintf( buf, "Test: %d, not one %d\n", 1); // 实参少1个
VS2013下得到的输出:Test: 1, not one -84618255
其实后面显示的数是随机的,就是函数调用栈实参1后面的一个4字节数,这个例子不会导致宕机,因为第2个实参取的是栈上的随机数(未初始化数)。
3. 参数类型不匹配
如果format参数中有%s,则对应的实参一定得给对了,否则极其可能宕机:
char buf[1024];double dV = 123.0;
int iLen = sprintf( buf, "Test: %s, not one %d\n", dV, 1);std::cout << buf;
在Debug模式下,将断点设置在最后一行,将会发现调用栈完全不对了,因为sprintf将dV的值当字符串地址看待,所以宕掉
char buf[1024];std::string str = "hello";
int iLen = sprintf( buf, "Test: %s, not one %d\n", str, 1);std::cout << buf;
这个也不会输出正常结果, 会把str对象(copy的对象)的空间当作字符串地址
VS2013下得到的输出: Test: (null), not one -858993460 (还算幸运,没宕机)
sprintf不会帮你做字符串转换,你的主动告诉它。
最后,第1个缓冲区参数,需要有足够的空间,否则很容易越界导致各种问题。
sprintf_s在缓冲区后加了个缓冲区大小参数,VS的实现会将缓冲区按缓冲区大小参数memset,所以,如果缓冲区大小参数不正确,又将可能导致新的问题--越界
原文链接:https://blog.csdn.net/Joal_zhu/article/details/38681583
字符串函数sprintf / sprintf_s 容易出错的地方相关推荐
- C 字符串函数 sprintf()、snprintf() 详解
一.sprintf() 函数详解 在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望. 由于 sprintf 跟 printf 在用法上几乎一样,只是打印的目的地不同而已,前者 ...
- Linux C 字符串函数sprintf()和snprinttf()
sprintf()函数详解 int sprintf( char *buffer, const char *format , - ); 函数说明:将格式化的字符串输入到buffer中. 函数返回值:bu ...
- PHP学习记录(字符串函数)
字符串常用函数 获取字符串长度函数 /* * strlen函数 * int strlen($var) * 获取字符串或数字的长度 */ $a = 'hello, woRld'; $b = '王昭'; ...
- 如果$.ajax函数迟迟得不到响应,那么最有可能出错的地方是请求参数写错了
如下的$.ajax函数 $.ajax({url: url,// 请求的地址data:{id:id,pieceId:pieceId,pieceDesc:pieceDesc,actualStock:act ...
- C语言再学习 -- 字符串和字符串函数
最近身体很不给力,很乏累!白天没精神,晚上睡不着,心情还很烦躁.看书都有点看不下去的样子,到了C语言最难掌握的部分了,数组.指针.字符串.硬着头皮看书总结吧. 一.字符串 1.字符串介绍 字符串是以空 ...
- c字符串函数实现(1)---strncpy
strncpy原型:char* strncpy(char* dest,const char* src,size_t count); 函数说明:1.当count <= strlen(src)+1( ...
- PHP常用字符串函数小结
最近面试被这个面到吐血,特地来fork一些. 来源:https://www.jb51.net/article/145084.htm 一.判断类型的函数 is_bool() //判断是否为布尔型 is_ ...
- PHP字符串函数大全
PHP字符串函数大全 AddSlashes: 字符串加入斜线. bin2hex: 二进位转成十六进位. Chop: 去除连续空白. Chr: 返回序数值的字符. chunk_split: 将字符串分成 ...
- C语言之字符串探究(五):N系列字符串函数——strncpy、strncat、strncmp
相关博文:C++之char和string字符串类探究 相关博文:C语言之数组探究(一):定义.大小.初始化.访问和三要素 相关博文:C语言之字符串探究(一):字符串与字符数组 相关博文:C语言之字符串 ...
- printf函数,fprintf函数,sprintf函数
printf 函数作用:格式化输出函数, 一般用于向标准输出设备按规定格式输出信息. 原型 extern int printf(const char *format,...); 用法 //以下程序用于 ...
最新文章
- mysql悲观锁和乐观锁
- Asp.Net MVC中Action跳转小结
- 【计算机网络】数据链路层 : 差错控制 ( 纠错编码 | 海明码 | “海明码“ 原理 | “海明码“ 工作流程 | 确定校验啊位数 | 确定校验码和数据位置 | 求校验码值 | 检错纠错 )★
- http经典书籍--http权威指南
- linux echo 变量 字符串,echo命令 – 输出字符串或提取Shell变量的值
- Java里的字符串, String类简单介绍.
- 【bzoj3879】SvT 后缀数组+倍增RMQ+单调栈
- 第四范式携手智源研究院 共推全球最大智能模型应用发展
- java中 flush()方法
- mysql改原始密码mac_MAC版修改MySQL初始密码的方法
- Python学习day2 while循环格式化输出运算符
- aix创建oracle表空间,Oracle for AIX基于裸设备的表空间扩充步聚
- 大数据Hadoop之——任务调度器Oozie(Oozie环境部署)
- 计算机2.0培训心得,2020信息技术2.0培训心得
- 这一本《电子工程师技术手册》,你要不要?
- 金山打字测试一分钟软件,金山打字2006——一款打字练习及测试软件.doc
- B站的热门视频要怎么同时批量下载保存到本地电脑中
- java实战--GC终极总结
- 看aps高级排产如何实现生产计划智能排产
- pdf转换成word转换器免费版
热门文章
- rc.local文件开机不执行
- java 求集合真子集_干货 | 集合与函数概念知识点总结
- 电脑网络禁用了怎么恢复_Tenorshare UltData for Mac(iOS数据恢复备份软件)v9.4.1中文激活版_软件动态论坛...
- A. Death Note
- HDU3853:LOOPS
- C语言,使用结构体读入两个在同一年的日期,判断日期是否合法,并计算两个日期之间相差的天数。结构体定义如下:...
- [C++]类的继承与派生
- TFS无法连接:TF31002
- cvErode() 形态腐蚀(可多次)
- 索尼便携式无线服务器,WF-SP900体验报告:2018索尼真无线产品中的顶端存在