C语言 使用 sprintf 打印size_t需要多少个字符



我想做这样的事情:

char sLength[SIZE_T_LEN];
sprintf(sLength, "%zu", strlen(sSomeString));

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

sizeof(size_t) * CHAR_BIT

limits.h开始)给出了位数。对于十进制输出,为了安全起见,请使用每位数 3(十六进制为 4)位的(粗略)较低估计值。不要忘记为字符串的nul终止符添加1

所以:

#include <limits.h>
#define SIZE_T_LEN ( (sizeof(size_t) * CHAR_BIT + 2) / 3 + 1 )

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

请注意,这给出了一个上限,并且由于使用了CHAR_BIT,因此是完全可移植的。要获得确切的值,您必须使用log10(SIZE_MAX)(请参阅JohnBollinger对此的回答)。但这会产生浮点数,并且可以在运行时计算,而上面的版本是编译时评估的(并且可能比粗略估计的成本更高)。除非您有一个非常受 RAM 约束的系统,否则没关系。在这样的系统上,无论如何您都应该避免使用stdio

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

考虑到字符串终止符的空间,确切的答案是

 log10(SIZE_MAX) + 2

其中SIZE_MAX宏在 stdint.h 中声明。 不幸的是,这不是编译时常量(由于使用了log10())。 如果您需要在编译时计算的编译时常量,则可以使用以下命令:

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

这给出了至少 256 位size_t的正确答案。 它基于这样一个事实,即 210 非常接近 1000。 在某些大量位上,它将太小一,而对于更多的位,它将进一步落后。 如果您担心如此大的size_t那么您可以在结果中添加一个甚至两个。

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

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

在字符使用 8 位表示的系统上,

如果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("%sn", str);
   a = 0xFFFFFFFFFFFFFFFF;
   sprintf(str, "%zu", a);
   printf("%sn", str);
}

输出:

4294967295
18446744073709551615

很容易使其适应使用 16 位表示字符的系统。

最新更新