百篇大计敬本年之C语言巅峰之道《五》—— snprintf 是否需要 memset 缓冲区
发布日期:2021-08-30 07:11:53 浏览次数:15 分类:技术文章

本文共 2294 字,大约阅读时间需要 7 分钟。

  hot3.png

    代码中经常用到 snprintf 函数,每次使用前都会 memset 一下缓冲区,感觉效率不高,今天突然想到是否真需要在使用前进行memset操作呢?

    网络上找到的说法有些说不需要,有些说养成习惯。

    我决定找找 snprintf 操作的本质,其身为传说中最安全的函数,必然有其道理。

#include 
#include
#include
/** len 大小不得大于 pData 缓冲区的大小,否则崩崩崩崩崩崩。。。。*/static int reprint(char *pData, int len){ if ((NULL == pData) || (0 >= len)) { return -1; } int j; printf("The data:"); for (j = 0; j < len; j++) { printf("%02x ", pData[j]); } printf("\n"); return 0;}int main(){ char dataPath[12] = {0}; memset(dataPath, '2', sizeof(dataPath)); printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath)); reprint(dataPath, sizeof(dataPath)); snprintf(dataPath, sizeof(dataPath), "123455678"); printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath)); reprint(dataPath, sizeof(dataPath)); snprintf(dataPath, sizeof(dataPath), "1234567890987654321"); printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath)); reprint(dataPath, sizeof(dataPath)); snprintf(dataPath, strlen("22222"), "22222"); printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath)); reprint(dataPath, sizeof(dataPath)); #if 0 snprintf(dataPath, strlen("1234567890987654321"), "1234567890987654321"); printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath)); reprint(dataPath, sizeof(dataPath));#endif return 0;}

输出如下:

$ ./a.out 30->222222222222 <12>The data:32 32 32 32 32 32 32 32 32 32 32 32   /*(这是标志-> 打印1)*/31->123455678 <9>The data:31 32 33 34 35 35 36 37 38 00 32 32   /*(这是标志-> 打印2)*/35->12345678909 <11>The data:31 32 33 34 35 36 37 38 39 30 39 00   /*(这是标志-> 打印3)*/39->2222 <4>The data:32 32 32 32 00 36 37 38 39 30 39 00   /*(这是标志-> 打印4)*/

从输出结果中可得出几个结论:

    1、snprintf 函数在格式化输出字串后面的会自动补'\0'

    2、snprintf 在 buf 容量不足时会截断数据

    3、snprintf 在容量充足的时候不会对后面的数据清零

    另外,snprintf 第二个参数大小不能大于 第一个参数空间大小,不信可打开这段代码测试

#if 1	snprintf(dataPath, strlen("1234567890987654321"), "1234567890987654321");	printf("%d->%s <%d>\n", __LINE__, dataPath, strlen(dataPath));		reprint(dataPath, sizeof(dataPath));#endif

    在 Linux 上运行会 core dump!

    So,至于要不要每次在 snprintf 前使用 memset 清空缓冲区,就看实际需求了。

    PS:从上面的结论可知:如果单单是字符串,可不用清空,提高效率。

    还有一个疑问,第二个参数大于第一个参数的空间大小时会崩溃,那么这样还算不算安全函数呢?

    但不管怎么说,只要程序员控制好第二个参数,这个函数相对其他函数还是非常安全的,值得推荐的!

    我以前也用过sprintf,但是知道snprintf之后我就一直没用过sprintf,同事用 sprintf 我也会建议他用snprintf!

转载于:https://my.oschina.net/bingwu/blog/1517682

转载地址:https://blog.csdn.net/weixin_34026276/article/details/91749952 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:我的友情链接
下一篇:KeyMob广告携广告主与开发者,共创2016移动广告平台

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月15日 04时46分01秒