snprintf,用于 C 中整数到字符串的转换
我有一小段代码可以将 c 中的整数转换为字符串。 该代码必须在 32 位和 64 位平台上运行。
我正在循环中解析参数,因此我需要 malloc 来创建缓冲区
int tmp_integer = /*read as integer*/
char* tmp_string = malloc(20* sizeof(char)); /*enough room for the biggest integer*/
snprintf(tmp_string, 20,"%d",tmp_integer); /*can I avoid using 20 here*/
a[i - 1] = tmp_string; /*save the parsed argument for final usage*/
我的问题是: 有什么办法可以让它变得很好使用 snprintf,或者我应该回退到 sprintf。
我认为使用 snprintf 不是正确的做法,因为最初我想防止缓冲区溢出,但由于整数的大小已知,我认为它是无用的。我仍然想知道这里的最佳实践是什么。
I have a little piece of code to convert an integer to a string in c.
The code has to work on both 32-bits and 64 bits platform.
I am parsing arguments in a loop, so I need malloc to create the buffer
int tmp_integer = /*read as integer*/
char* tmp_string = malloc(20* sizeof(char)); /*enough room for the biggest integer*/
snprintf(tmp_string, 20,"%d",tmp_integer); /*can I avoid using 20 here*/
a[i - 1] = tmp_string; /*save the parsed argument for final usage*/
My question is :
Is there any way to make it nice using snprintf, or should I fall back to sprintf.
I figured that using snprintf was not the right thing to do, because originally I wanted to be protected from buffer overruns, but since the size of integer is known I think it is useless. Still I would like to know what is the best practice here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在这种情况下你是对的。您知道您的数字不大于 64 位,并且您知道这意味着它的位数不会超过 20 位。因此,您实际上并不需要使用
snprintf
。Bug:最大的无符号 64 位数字是 18,446,744,073,709,551,615,即 20 位数字。但是,每个字符串末尾都有一个
'\0'
(NUL
) 字符(因此称为 nul 终止字符串术语)。因此,您应该为数组分配 21 字节,而不是 20。You are right in this case. You know your number is not bigger than 64bits, and you know that it means it won't have more than 20 digits. Therefore, you don't really need to use
snprintf
.Bug: The biggest unsigned 64 bit number you can have is 18,446,744,073,709,551,615 which is 20 digits. However, each string has a
'\0'
(NUL
) character in the end (hence the nul-terminated string terminology). Therefore, you should allocate 21 bytes for your array and not 20.如果动态分配内存,则可以使用 log10 来计算字符串中所需的位置数:
If you allocate memory dynamically, you can use log10 to calculate the number of places needed in your string:
问题是那个神奇的“20”从何而来。由于它很神奇,因此它应该表示为符号常量,而不是代码中重复的整数文字。使用符号常量还具有让编译器为您进行错误检查的好处:(
另请注意我如何删除
sizeof (char)
内容,因为它完全多余并且(imo)非常混乱。)从性能的角度来看,您可能可以取消字符串格式化程序的受保护变体,但由于您无论如何都在这里调用
malloc()
(不便宜),因此它可能不是一个很好的选择赢来删除它。The question becomes where that magical "20" came from. Since it's magical, it should be represented as a symbolic constant, not an integer literal repeated in the code. Using a symbolic constant also has the benefit of having the compiler do the error-checking for you:
(Also notice how I dropped the
sizeof (char)
thing, since it's totally redundant and (imo) very cluttering.)From a performance point of view, you can probably do away with the protected variant of the string formatter, but since you're calling
malloc()
here anyway (not cheap) it's probably not a great win to remove it.您可以在临时缓冲区中使用 sprintf ,然后分配合适的大小(随着 sprintf 的返回),然后将临时值复制到缓冲区中。
You can sprintf in a temp buffer and then alloc the good size (with the return of sprintf), and then copy the temp into your buffer.
这是另一种(可能不是那么漂亮)基于 sum1stolemyname 代码片段进行转换的方法:
This is another (maybe not so pretty) way to convert it based on sum1stolemyname code snippet:
解决此问题的一个简单、可移植(跨不同位数、平台和 CPU)的解决方案是:
A simple, portable (across various bitnesses, platforms and cpus) solution to this problem is: