使用snprintf()有效确定字符数组大小

我们从大学有一个小任务,要求我们在C中执行一些工作。部分问题是转换一个无符号长号,这是在程序过程中生成的,因此无需预先确定它,串。 当然,我使用了snprintf 。 我初始化了一个数组(str [50]),该数组的大小足以避免任何类型的缓冲区错误。

然而,在提交时,我的教授说我的避免缓冲区错误的方法是无效的。

我现在的问题是,当我创建一个char数组来保存unsigned long值时,我的大小是多少? 是否有一些C宏来帮助确定无符号长号可以容纳的最大字符数?

可能像是,

 char str[MAX_NUMBER_OF_DIGITS_OF_UNSIGNED_LONG_ON_MACHINE]; 

我已经浏览了limit.h和一些博客和这个论坛,但没有任何协议。 任何帮助,将不胜感激!

为简洁起见,请使用@BLUEPIXY 。

更深层次的答案。

C允许各种“区域设置”,使得理论上, snprintf(..., "%lu",...)可以打印比预期更长的字符串。 而不是“1234567”,输出可能是“1,234,567”。

推荐:
1.确定最大整数的位大小n
2. n * log2(10)向上舍入+ 1然后得到字数。
3.设置最大需要2倍的缓冲区。
4.检查snprintf结果。
5.关键问题:使用带有snprintf()的双重调用需要确保“语言环境”和号码不会在调用之间发生变化 – 这里不使用,因为snprintf()是一个function上很昂贵的调用。

 char *ulong_to_buf(char *buf, size_t size, unsigned long x) { int n = snprintf(buf, size, "%lu", x); if (n < 0 || n >= size) return NULL; return buf; } // Usage example void foo(unsigned long x) // 1/3 --> ~log2(10) #define ULONG_PRT_LEN (sizeof(unsigned long)*CHAR_BIT/3 + 2) char buf[ULONG_PRT_LEN*2 + 1]; // 2x for unexpected locales if (ulong_to_buf(, sizeof buf, x)) { puts(buf); } 

如果真的关心代码,那么简单编写自己的代码

 #include  #include  #include  #define PRT_ULONG_SIZE (sizeof(unsigned long) * CHAR_BIT * 10 / 33 + 3) char *ulong_strnull(int x, char *dest, size_t dest_size) { char buf[PRT_ULONG_SIZE]; char *p = &buf[sizeof buf - 1]; // Form string *p = '\0'; do { *--p = x % 10 + '0'; x /= 10; } while (x); size_t src_size = &buf[sizeof buf] - p; if (src_size > dest_size) { // Not enough room return NULL; } return memcpy(dest, p, src_size); // Copy string } 
 #if ULONG_MAX == 4294967295UL # define SIZE (10 + 1) #elif ULONG_MAX <= 18446744073709551615ULL # define SIZE (20 + 1) #endif 

snprintf的文档:

关于snprintf()的返回值,SUSv2和C99相互矛盾:当使用size = 0调用snprintf()时,SUSv2规定一个小于1的未指定返回值,而C99允许str在这种情况下为NULL,并给出返回值(一如既往)为在输出字符串足够大的情况下写入的字符数。

如果您使用的是C99,则可以使用snprintf确定大小(如BLUEPIXY所述):

 int size = snprintf(NULL, 0, "%lu", ULONG_MAX); 

但是,如果您不能使用C99,则可以通过确定所需的位数并为终止\0字符添加其他字符来确定字符串大小:

 int size = (int) log10((double) ULONG_MAX) + 1; 

为了使用size字节分配数组,您可以简单地使用

 char str[size]; 

但是,这只适用于您的编译器/版本支持VLA ,如果编译器不支持此function,您可以动态分配数组

 char *str = malloc(size); //< Allocate the memory dynamically // TODO: Use the str as you would the character array free(str); //< Free the array when you are finished