使用sprintf打印size_t需要多少个字符?

时间:2016-01-26 17:24:32

标签: c string types printf size

我想做这样的事情:

char sLength[SIZE_T_LEN];

sprintf(sLength, "%zu", strlen(sSomeString));

也就是说,我想在缓冲区中打印size_t类型的值。问题是:SIZE_T_LEN的价值应该是多少?关键是要知道所需的最小尺寸,以确保永远不会发生溢出。

4 个答案:

答案 0 :(得分:8)

sizeof(size_t) * CHAR_BIT(来自limits.h)给出位数。对于十进制输出,使用每个数字的(粗略)低估计3(十六进制4)位在安全端。不要忘记为字符串的1终止符添加nul

所以:

#include <limits.h>

#define SIZE_T_LEN ( (sizeof(size_t) * CHAR_BIT + 2) / 3 + 1 )

这会产生类型size_t本身的值。在典型的8/16/32/64位平台上,+ 2不是必需的(size_t的最小可能大小为16位)。这里的错误已经足够大,可以产生正确的截断结果。

请注意,这会给出一个上限,并且由于使用CHAR_BIT而完全可移植。要获得准确的值,您必须使用log10(SIZE_MAX)(请参阅JohnBollinger的答案)。但是这产生了一个浮点数并且可能在运行时计算,而上面的版本是编译时评估的(并且可能比粗略估计的成本更多)。除非你有一个RAM限制系统,否则没问题。在这样的系统上,你应该避免使用stdio

为了绝对安全起见,您可能希望使用snprintf(但这不是必需的)。

答案 1 :(得分:3)

确定字符串终结符空间的确切答案是

 log10(SIZE_MAX) + 2

SIZE_MAX中声明了stdint.h宏。不幸的是,这不是编译时常量(由于log10()的使用)。如果你需要一个在编译时计算的编译时常量,那么你可以使用它:

sizeof(size_t) * CHAR_BIT * 3 / 10 + 2

这为size_t提供了至少256位的正确答案。它基于2 10 非常接近1000的事实。在一些大的位上,它将太小一个,而对于更大的位数,它将进一步下降背后。如果您担心这么大size_t,那么您可以在结果中添加一个甚至两个。

答案 2 :(得分:2)

如果您可以使用snprintf,请使用:

int len = snprintf (NULL, 0, "%zu", strlen (sSomeString));

答案 3 :(得分:0)

在使用8位表示char的系统上

如果sizeof(size_t)为2,则最大值为:65535
如果sizeof(size_t)为4,则最大值为:4294967295
如果sizeof(size_t)为8,则最大值为:18446744073709551615
如果sizeof(size_t)为16,则最大值为:3.4028237e + 38

您可以使用该信息使用预处理器提取字符串的最大大小。

示例程序:

#include <stdio.h>

#ifdef MAX_STRING_SIZE
#undef MAX_STRING_SIZE
#endif

// MAX_STRING_SIZE is 6 when sizeof(size_t) is 2
// MAX_STRING_SIZE is 11 when sizeof(size_t) is 4
// MAX_STRING_SIZE is 21 when sizeof(size_t) is 8
// MAX_STRING_SIZE is 40 when sizeof(size_t) is 16
// MAX_STRING_SIZE is -1 for all else. It will be an error to use it 
// as the size of an array.

#define MAX_STRING_SIZE (sizeof(size_t) == 2 ? 6 : sizeof(size_t) == 4 ? 11 : sizeof(size_t) == 8 ? 21 : sizeof(size_t) == 16 ? 40 : -1)

int main()
{
   char str[MAX_STRING_SIZE];
   size_t a = 0xFFFFFFFF;

   sprintf(str, "%zu", a);
   printf("%s\n", str);

   a = 0xFFFFFFFFFFFFFFFF;
   sprintf(str, "%zu", a);
   printf("%s\n", str);
}

输出:

4294967295
18446744073709551615

很容易使它适应使用16位表示char的系统。