获取用于 sprintf 处理 longs C 的 char 缓冲区的大小

Get size of char buffer for sprintf handling longs C

我是 C 的新手,在 C 中处理 long ints/char* 时遇到了一个问题。我想将 long 存储在 char* 中,但我不确定我应该如何管理我的缓冲区的大小以适应任何给定的长度。 这就是我想要的:

char buffer[LONG_SIZE]; // what should LONG_SIZE be to fit any long, not depending on the OS?
sprintf(buffer, "%ld", some_long);

我需要使用 C 而不是 C++。如果我不想使用幻数,有什么解决办法吗?

if I don't want to use magic-numbers

使用带有 0 长度缓冲区的 snprintf() 将 return 保存结果所需的字符数(减去尾随的 0)。然后,您可以分配足够的 space 来按需保存字符串:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(void) {
  long some_long = LONG_MAX - 5;
  // Real code should include error checking and handling.
  int len = snprintf(NULL, 0, "%ld", some_long);
  char *buffer = malloc(len + 1);
  snprintf(buffer, len + 1, "%ld", some_long);
  printf("%s takes %d chars\n", buffer, len);
  free(buffer);
}

还有 asprintf(),在 Linux glibc 和一些 BSD 中可用,它为您分配结果字符串,具有比上述更方便(但便携性较差)的接口。

按需分配所需 space 而不是使用固定大小有一些好处;例如,如果您将来更改格式字符串,它将继续工作而无需进一步调整。

即使您坚持使用固定长度的缓冲区,我也建议您使用 snprintf() 而不是 sprintf() 以确保您不会以某种方式覆盖缓冲区。

使用 snprintf 计算必要的大小可能更正确,但看起来应该可行:

char buf[ sizeof(long) * CHAR_BIT ];

long中的位数是sizeof long * CHAR_BIT。 (CHAR_BIT<limits.h>中定义。)这最多可以表示一个大小为2sizeof long * CHAR_BIT - 1.

的有符号数

这样的数最多可以有floor(log102sizeof long * CHAR_BIT - 1)+1位小数。这是 floor((sizeof long * CHAR_BIT - 1) * log102) + 1。log102 小于 .302,所以 (sizeof long * CHAR_BIT - 1) * 302 / 1000 + 1 个字节就足够了。

符号加一,终止空字符加一,char[(sizeof long * CHAR_BIT - 1) * 302 / 1000 + 3]足以作为缓冲区。