使用 sprintf 打印 size_t 需要多少个字符?
How many chars do I need to print a size_t with sprintf?
我想做这样的事情:
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 位平台上,不需要 + 2
(size_t
的最小可能大小是 16 位)。这里的错误已经大到足以产生正确截断的结果。
请注意,这给出了上限并且由于使用 CHAR_BIT
是完全可移植的。要获得精确值,您必须使用 log10(SIZE_MAX)
(请参阅 JohnBollinger 的回答)。但这会产生一个浮点数,可能会在 run-time 处计算,而上面的版本是 compile-time 评估的(并且可能已经比粗略估计花费更多的堆栈)。除非你有一个非常受 RAM 限制的系统,否则没关系。在这样的系统上,您无论如何都应该避免使用 stdio
。
为了绝对安全起见,您可能需要使用 snprintf
(但这不是必需的)。
如果可以使用snprintf,请使用:
int len = snprintf (NULL, 0, "%zu", strlen (sSomeString));
字符串终止符 space 的确切答案是
log10(SIZE_MAX) + 2
其中 SIZE_MAX
宏在 stdint.h
中声明。不幸的是,这不是 compile-time 常量(由于使用了 log10()
)。如果你需要一个 compile-time 常量,它是在 在 编译时计算的,那么你可以使用这个:
sizeof(size_t) * CHAR_BIT * 3 / 10 + 2
这给出了 size_t
至少 256 位的正确答案。它基于 210 非常接近 1000 的事实。在一些大量的位上它会太小一个,而对于更多的位数它会进一步落后.如果您担心这么大 size_t
那么您可以在结果中添加一个甚至两个。
在使用 8 位表示字符的系统上,
若sizeof(size_t)
为2,则最大值为:65535
如果sizeof(size_t)
为4,则最大值为:4294967295
如果sizeof(size_t)
为8,则最大值为:18446744073709551615
如果sizeof(size_t)
为16,则最大值为:3.4028237e+38
您可以使用该信息使用 pre-processor 来提取字符串的最大大小。
示例程序:
#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 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 位平台上,不需要 + 2
(size_t
的最小可能大小是 16 位)。这里的错误已经大到足以产生正确截断的结果。
请注意,这给出了上限并且由于使用 CHAR_BIT
是完全可移植的。要获得精确值,您必须使用 log10(SIZE_MAX)
(请参阅 JohnBollinger 的回答)。但这会产生一个浮点数,可能会在 run-time 处计算,而上面的版本是 compile-time 评估的(并且可能已经比粗略估计花费更多的堆栈)。除非你有一个非常受 RAM 限制的系统,否则没关系。在这样的系统上,您无论如何都应该避免使用 stdio
。
为了绝对安全起见,您可能需要使用 snprintf
(但这不是必需的)。
如果可以使用snprintf,请使用:
int len = snprintf (NULL, 0, "%zu", strlen (sSomeString));
字符串终止符 space 的确切答案是
log10(SIZE_MAX) + 2
其中 SIZE_MAX
宏在 stdint.h
中声明。不幸的是,这不是 compile-time 常量(由于使用了 log10()
)。如果你需要一个 compile-time 常量,它是在 在 编译时计算的,那么你可以使用这个:
sizeof(size_t) * CHAR_BIT * 3 / 10 + 2
这给出了 size_t
至少 256 位的正确答案。它基于 210 非常接近 1000 的事实。在一些大量的位上它会太小一个,而对于更多的位数它会进一步落后.如果您担心这么大 size_t
那么您可以在结果中添加一个甚至两个。
在使用 8 位表示字符的系统上,
若sizeof(size_t)
为2,则最大值为:65535
如果sizeof(size_t)
为4,则最大值为:4294967295
如果sizeof(size_t)
为8,则最大值为:18446744073709551615
如果sizeof(size_t)
为16,则最大值为:3.4028237e+38
您可以使用该信息使用 pre-processor 来提取字符串的最大大小。
示例程序:
#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 位表示字符的系统。