确定 char 数组的大小以使用预处理器转换数字

Determine size of char array to convert numbers with the preprocessor

我每天都在面对这个简单的“问题”,但还没有好的解决方案:

char text[STRING_LENGTH + 1] = ""; 
int32_t number = -12312313; 
itoa(number, text, 10); //or sprintf(text, "%d", number);

如何在预处理器中确定 STRING_LENGTHSTRING_LENGTH 应该是要转换的类型可以产生的最大长度。在我的例子中 int32_t => 11。 当然,我可以这样做:

#define INT32_STRING_LENGTH 11
#define UINT32_STRING_LENGTH 10
//...

但似乎应该已经有解决方案了。

在这种情况下,使用 snprintf 也是一个选项,但这会在应用程序已经 运行 时计算长度。 运行(如果你有一些空闲字节):

int32_t number = -12312313; 
char text[snprintf(NULL, 0, "%d", number) + 1];
snprintf(text, sizeof(text), "%d", number);

也许有使用 "%d""%lu"、...的解决方案?

如果我在这里提到的任何地方有误,请纠正我。

提前致谢!

The GNU Portability Library has an amazing single header intprops part which has some amazing code available from github/coreutils/gnulib/intprops.h。 header 包含 INT_BUFSIZE_BOUNDINT_STRLEN_BOUND:

/* Bound on buffer size needed to represent an integer type or expression T,
   including the terminating null.  T must not be a bit-field expression.  */
#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1)

包含使用示例的文档可在文档 https://www.gnu.org/software/gnulib/manual/html_node/Integer-Bounds.html :

中找到

INT_BUFSIZE_BOUND (t) is an integer constant expression that is a bound on the size of the string representing an integer type or expression t in decimal notation, including the terminating null character and any leading - character. For example, if INT_BUFSIZE_BOUND (int) is 12, any value of type int can be represented in 12 bytes or less, including the terminating null. The bound is not necessarily tight.

Example usage:

#include <intprops.h>
#include <stdio.h>
int
int_strlen (int i)
{
  char buf[INT_BUFSIZE_BOUND (int)];
  return sprintf (buf, "%d", i);
}

请注意 header 在 GNU Lesser General Public 许可证下。请记住复制 header with license 并通过一些贡献和许可分发您的软件。然后:

int32_t number = -12312313; 
char text[INT_BUFSIZE_BOUND(int32_t)];
// or    [INT_BUFSIZE_BOUND(-12312313)];
sprintf(text, "%"PRId32, number);

请注意,%d 可能对 int32_t 无效。使用来自 inttypes.h.

的标准 PRId32

实现的核心是这个很好的函数,它可用于基本计算一个数字的 log10 作为常量表达式:

/* Bound on length of the string representing an unsigned integer
   value representable in B bits.  log10 (2.0) < 146/485.  The
   smallest value of B where this bound is not tight is 2621.  */
#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485)

所以基本上要获得最大缓冲区大小长度,获得类型的位数,计算该位数的 * 146 + 484) / 485),为减号添加 +1 并添加 +1 对于零终止字节 - 这是您需要的字节数。