C函数snprintf的用法和避免踩坑
snprintf 函数是C语言中非常常用的一个函数,它的作用是格式化一段文本放到指定的缓存中。和它类似的还有sprintf, vsnprintf等。它们都完成类似的功能,但又有些区别,如sprintf 是不会检查输出缓存的长度的,需要调用者确保长度是足够的。vsnprintf 函数和snprintf 很像,但它是通过 va_list 来传入格式化参数,所以一般用于传入了可变的需要格式化字符串的函数内。而我们最常用的就是snprintf 了,因为它具有缓冲区的溢出保护。
snprintf函数的原型如下: int snprintf(char *str, size_t size, const char *format, ...);
其中: str 传入输出缓冲区的地址;size指出输出缓冲区的大小;format 为传入的格式化字符串;其后的参数就是格式化的参数了。
该函数返回一个整数,表示格式化后的文本大小。通过这个返回值,我们可以做很多事情。也正是对这个返回值的理解不够或者使用错误,我们往往会踩一些坑。
最普通的用法是使用该函数来格式化一段文本,如: char szText[1024]; int a=10, b=20; snprintf(szText, sizeof(szText), "%d + %d = %d", a, b, a+b);
该函数具有缓冲区保护的功能,如果格式化输出内容超过了缓冲区的最大长度,那么输出字符串会被截断到缓冲区的最大长度。同时无论如何,字符串最后的结尾 ‘ ’ 是一定会有的,保证了输出的字符串不会溢出。所以这也是广大程序员喜欢使用这个函数的原因。
如果我们需要格式化一个具有多个元素的数组,那么这个时候就可以充分利用snprintf的返回值了。我们只需要反复调用snprintf 并移动缓冲区的起始位置就能实现。代码如下: char szText[1024]; // 输出的缓冲区 int a[100] = {...}; // 假设会有代码逻辑填充这个数组的内容 int n; // 循环数组的下标 int len = snprintf(szText, sizeof(szText), "a= {"); // 保存输出字符串的长度 for (n = 0; n < 100; n++) { len += snprintf(szText + len, sizeof(szText)-len, "%d, ", a[n]); } len += snprintf(szText + len, sizeof(szText)-len, "}");
这段代码看起来能正常工作,通常也确实可以正常工作,但是前提条件是 szText的缓冲区大小是足够大的。如果缓冲区的大小不够会发生什么情况?你不妨改小szText再试试。
那么为什么会出现问题呢?首先我们要深入理解一下snprintf 返回值的含义。按前面所述,返回值表示格式化后文本的大小,注意不是返回输出缓冲内的字符串长度。什么意思呢,也就是说,如果输出的缓冲足够大,大到可以容纳所有的输出文本,那么这个返回的长度恰恰就是输出缓存中的字符串长度。如果输出缓冲不够大,或者根本就没有传入输出缓冲这个参数呢?返回值就和实际的输出文本长度不一样了。为什么是这样?其实这个函数本来也是可以用来计算格式化所需要的最小缓存大小,并根据返回值来实际分配输出缓冲的内存。如下代码所示的用法: int a = 10; int b = 20; char* pszOut = NULL; // 输出缓存指针 int len; len = snprintf(NULL, 0, "%d + %d = %d", a, b, a+b); // 计算需要的输出长度。 pszOut = (char*)alloca(len+1); // 需要考虑结尾的0 战用一个字符 snprintf(pszOut, len+1, "%d + %d = %d", a, b, a+b);
有人会疑惑,为什么需要这样写?上面这个例子可能不明显。但是如果需要格式化的内容不固定,长度变化范围很大。那么就有可能不太好使用固定大小的缓冲。
理解了这个返回值的含义和用法,再回到上面那个循环调用的例子。我们需要加上对长度的校验就没有问题了: char szText[1024]; // 输出的缓冲区 int a[100] = {...}; // 假设会有代码逻辑填充这个数组的内容 int n; // 循环数组的下标 int len = snprintf(szText, sizeof(szText), "a= {"); // 保存输出字符串的长度 for (n = 0; n < 100 && len < sizeof(szText); n++) { len += snprintf(szText + len, sizeof(szText)-len, "%d, ", a[n]); } len += snprintf(szText + len, sizeof(szText)-len, "}");
如果有什么疑问,欢迎一起讨论。
券商回应APP违法违规被通报检测提取的APP版本非官方正式发布南方财经4月25日电,国家计算机病毒应急处理中心近期通过互联网监测发现17款移动App存在隐私不合规行为,涉及13家券商APP和4家第三方炒股软件,违反网络安全法个人信息保护法等相
快手616购物节招商启动全程30天所有商家均可参与亿邦原创日前,快手电商召开了2022年616实在购物节招商启动会。本次616实在购物节以实在人,实在货,实在价为主题,整个活动划分为备战期(4月28日5月19日)和活动期(5月20
终于懂什么是分布式锁为什么要有分布式锁?模拟一个秒杀接口商品表单机情况下,用Jmeter发送1000个请求过来由于加了sychronized进行方法同步,结果正常。现在模拟集群环境,还是用上面的接口,
长视频困在会员系统里编辑导语会员系统自问世到现在已然被用户接受,长视频平台的会员费一直以来是其盈利的大头。而会员系统并没有那么完美,长视频被困在会员系统中,饱受争议,一起跟着作者探究一下吧!视频网站又
618电商平台iPhone手机价格随着电商平台大促日常化,前些年隔三差五的促销已经让消费者麻木,全年下来真正有影响力的两个促销节点,就剩618跟双11了。这两个节点更是消费者剁手之路上越不过去的坎。而智能手机的消费
有哪些去视频黑边的免费app?感谢邀请回答!1去除视频黑边的软件,推荐MP4RM转换专家软件可以将视频中的黑边去除掉,处理速度是较快的,导入rmvb视频,选择导出avi格式,在人性化影片画面裁剪功能,对视频黑边
三部门目标到2022年末,IPv6活跃用户数达到7亿网信办4月25日消息,日前,中央网信办国家发展改革委工业和信息化部联合印发深入推进IPv6规模部署和应用2022年工作安排,明确了2022年工作目标到2022年末,IPv6活跃用户
不敢与三星,苹果竞争,国产手机是软蛋?前两天聊国产手机集中冲高端,导致了不少品牌上的问题,有很多人都表示中国手机就是怂炮,只会窝里斗,为什么不一致对外?这个所谓的一致对外就是很扯的东西,首先现在手机竞争并没有涉及到国家
究竟什么是AppleID?什么是appleID?appleID是你在整个apple生态系统中的个人账户只需一个账户你就能访问所有apple产品和服务例如icloudappstore等等这意味着,如果你只用自
手机用久了,电池不耐用了怎么办?涨知识了冷知识手机用久了,电池越来越不耐用。一是由于电池损耗,寿命减少。二是由于产生虚电,从而导致手机电池不耐用。这时,先别急着去更换手机电池,可以试试手机上的补电功能,也许能够解决电池不耐用的
再次确定!vivoS15Pro下个月发布,4大升级让人心动4月25日消息,知名数码博主站哥曝光了vivoS15Pro的更多细节,再次提高了网友们对这款自拍旗舰的期待。结合此前的爆料和入网信息可知,vivoS15Pro将于5月份发布,在硬件