参考问题和答案 here:我可以使用此方法,以便解决方案与平台无关。
char *buff = (char*) malloc(sizeof(unsigned long)*8);
sprintf(buff, "%lu", unsigned_long_variable);
这里我得到缓冲区长度的值,因为它类似于unsigned long变量。这种方法是否正确?
答案 0 :(得分:3)
不要尝试来计算缓冲区大小。
从snprintf
开始,它会安全地告诉您需要多少个字符。然后你知道要分配多少字节来安全打印。
由于这是您不想一次又一次重复的几行代码,请编写一个完全符合您要求的函数malloc_printf
:在该函数中,调用snprintf
使用NULL目标,然后将malloc
缓冲区sprintf
放入malloc
缓冲区,并返回它。为了使其更快并且经常避免两个snprintf
和sprintf
调用,首先写入256个字符的缓冲区,这通常就足够了。
所以你的最终代码是
char* buff = malloc_printf ("%lu", unsigned_long_variable);
例如,使用格式%s%s
进行快速,安全且简单的字符串连接。
答案 1 :(得分:1)
如果有人构造一个C编译器,每个字符使用例如2000位,则输出可以溢出缓冲区。
您应该使用来自limits.h的8
而不是CHAR_BIT
。
另外,请注意,每3位需要(略小于)1个字符,字符串终止符需要1个字节。
所以,像这样:
#include <limit.h>
char *buff = malloc(1 + (sizeof(unsigned long) * CHAR_BIT + 2) / 3);
sprintf(buff, "%lu", unsigned_long_variable);
答案 2 :(得分:1)
不,这不是计算缓冲区大小的正确方法。
E.g。对于4字节无符号长整数,您的值最多为2 ^ 32-1 这意味着10位十进制数字。所以你的缓冲区需要11个字符。
您正在分配4 * 8 = 32。
正确的公式是
ceil(log10(2^(sizeof(unsigned long) * CHAR_BIT) - 1)) + 1
(log10
表示此处的十进制对数)
良好(安全)估计是:
(sizeof(unsigned long) * CHAR_BIT + 2) / 3 + 1
因为log10(2)小于0.33。
答案 3 :(得分:1)
您想知道需要多少个字符才能代表最大的unsigned long
。正确的吗?
为此,您正在尝试计算可能的最大unsigned long
:
sizeof(unsigned long)*8
这在几个方面都有问题。例如,sizeof
返回char
的倍数,不需要是8位。您应该与CHAR_BIT
(来自<limits.h>
)相乘。但即使这样也没有必要,因为相同的标题已经提供了最大可能的值 - UCHAR_MAX
。
然后你犯了一个错误:你的计算给出了unsigned long
的整数表示的大小。您想要的是字符中字符串表示的大小。这可以通过log10()
函数(来自<math.h>
):
log10( UCHAR_MAX )
这将为您提供一个double
值,表示UCHAR_MAX
中的(十进制)数字。这将是一个分数,你需要围绕向上(1)(ceil()
为你做这个。)
因此:
#include <math.h>
#include <stdlib.h>
#include <limits.h>
int main()
{
char * buff = malloc( ceil( log10( UCHAR_MAX ) ) + 1 );
//...
}
总而言之,这是非常狡猾的(我在写这篇文章时犯了两个错误,对我感到羞耻 - 如果你在使用它时犯了错误,羞辱你)。并且它需要使用数学库来snprintf( NULL, ... )
可以更轻松地为您做的事情,如您链接到的Q&amp; A所示。
(1):log10( 9999 )
为{em>四 - 数字提供3.9999565...
。
答案 4 :(得分:1)
简短回答:
#define INTEGER_STRING_SIZE(t) (sizeof (t) * CHAR_BIT / 3 + 3)
unsigned long x;
char buf[INTEGER_STRING_SIZE(x)];
int len = snprintf(buf, sizeof buf, "%lu", x);
if (len < 0 || len >= sizeof buf) Handle_UnexpectedOutput();
OP对sizeof(unsigned long)*8
的使用很弱。在CHAR_BIT
(每char
个位数)较大(必须至少为8)的系统上,sizeof(unsigned long)
可以是1. 1*8
char
对4294967295
来说肯定太小了(ULONG_MAX
的最小值)。
关于:sprintf()/snprintf()
鉴于 locale 问题,理论上,代码可能会打印其他字符,如4,294,967,295
,因此会超出预期的缓冲区。除非出现非常严格的内存限制,否则建议使用2倍预期大小的缓冲区。
char buf[ULONG_STRING_SIZE * 2]; // 2x
int len = snprintf(buf, sizeof buf, "%lu", x);
打印某些无符号整数的预期最大字符串宽度为ceil(log10(unsigned_MAX)) + 1
。在unsigned long
的情况下,ULONG_MAX
的值肯定不会超过pow(2,sizeof (unsigned long) * CHAR_BIT) - 1
,因此代码可以使用:
#define LOG10_2 0.30102999566398119521373889472449
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT * LOG10_2 + 2)
// For greater portability, should use integer math.
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT / 3 + 2)
// or more precisely
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT * 28/93 + 2)
如果指定了签名的整数,则使用+3
的简短答案。