c-用预处理器确定字符数组的大小以转换数字



我面对的是这个简单的"问题";实际上每天都有,但还没有一个好的解决方案:

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

如何在预处理器中确定STRING_LENGTHSTRING_LENGTH应该是要转换的类型可能产生的最大长度。在我的情况下CCD_ 3=>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"…的解决方案。。。?

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

提前感谢!

GNU可移植性库有一个惊人的单头intprops部分,其中有一些惊人的代码可从github/coreutils/gnulib/intprops.h获得。头包含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(是一个整数常量表达式绑定到表示整数类型的字符串的大小,或者十进制表示法中的表达式t,包括终止的null角色和任何主角。例如,如果INT_BUFSIZE_BOUND(INT(是12,任何INT类型的值都可以是以12个字节或更少的字节表示,包括终止null。这个绑定不一定很紧。

示例用法:

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

请注意,标头是在GNU较宽松通用公共许可证下。请记住使用许可证复制标题,并使用一些贡献和许可证分发您的软件。然后只是:

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,这就是你需要的字节数。

最新更新