问题正是你的编译器告诉你的;您不允许初始化 VLA。 Zack 在 cmets 中给出了一个明显的解决方案:删除初始化。您将在此答案中找到工作示例,其中一些允许初始化,而另一些则不允许。您可以在 cmets 中找到更多相关信息。以下示例从最合理 (IMHO) 到最不合理(涉及使用 malloc)排序,用于为表示数字的十进制数字序列分配存储空间。
我建议使用与八进制相同的技巧来确定将 int 值存储为十进制数字所需的字节数:将 int 中的总位数除以 3 并加上任何符号和 NUL 终止。 digit_count 可以写成这样的预处理宏:
#include <limits.h>
#include <stddef.h>
#include <stdio.h>
#define digit_count(num) (1 /* sign */ \
+ sizeof (num) * CHAR_BIT / 3 /* digits */ \
+ (sizeof (num) * CHAR_BIT % 3 > 0)/* remaining digit */ \
+ 1) /* NUL terminator */
int main(void) {
short short_number = -32767;
int int_number = 32767;
char short_buffer[digit_count(short_number)] = { 0 }; /* initialisation permitted here */
char int_buffer[digit_count(int_number)];
sprintf(short_buffer, "%d", short_number);
sprintf(int_buffer, "%d", int_number);
}
如您所见,这里的一个强大好处是digit_count 可以用于任何类型的整数而无需修改:char、short、int、long、long long,以及对应的unsigned 类型。
相比之下,一个小缺点是浪费了几个字节的存储空间,尤其是对于像 1 这样的小值。在许多情况下,该解决方案的简单性足以弥补这一点;在运行时计算小数位数所需的代码将占用内存中的更多空间,而不是这里浪费的空间。
如果您准备放弃上述代码的简单性和通用性,并且您真的想计算小数位数,Zacks 建议适用:删除初始化。这是一个例子:
#include <stddef.h>
#include <stdio.h>
size_t digit_count(int num) {
return snprintf(NULL, 0, "%d", num) + 1;
}
int main(void) {
int number = 32767;
char buffer[digit_count(number)]; /* Erroneous initialisation removed as per Zacks advice */
sprintf(buffer, "%d", number);
}
响应malloc 的建议:解决此问题的最不可怕的方法是避免不必要的代码(例如,调用malloc 和随后的free)。如果您不必从函数中返回对象,则不要使用malloc!否则,考虑存储到调用者(通过参数)提供的缓冲区中,以便调用者可以选择要使用的存储类型。这不是使用malloc 的合适替代方案,这种情况很少见。
但是,如果您决定为此使用malloc 和free,请以最不可怕的方式进行操作。避免对 malloc 的返回值进行类型转换和乘以 sizeof (char)(始终为 1)。以下代码是一个示例。使用上述任一方法计算长度:
char *buffer = malloc(digit_count(number)); /* Initialisation of malloc bytes not possible */
sprintf(buffer, "%d", number);
...完成后不要忘记free(buffer);。