【问题标题】:Create char array of integer using digits as size使用数字作为大小创建整数的 char 数组
【发布时间】:2013-06-03 04:29:16
【问题描述】:

我正在尝试在 C 中创建一个 char 数组,用 int 的数字填充它,但 int 可以是任意位数。

我正在使用一个名为 getDigits(int num) 的已创建函数,它返回 int 的位数。

char buffer[getDigits(number)] = "";
snprintf(buffer, sizeof(buffer),"%d",number);

但是当我使用 gcc 编译时,它返回:

error: variable-sized object may not be initialized

我什么都试过了。当我将其声明为char fileSizeStr[5] = ""; 时,它可以工作。当我尝试动态声明缓冲区大小时,我可以看到问题正在上升,但我真的很想知道是否有办法实现这一点。

【问题讨论】:

  • 使用 c99 编译器或使用 malloc
  • 尝试删除= ""snprintf 不关心其输出缓冲区中的内容。
  • gcc prog.c -std=c99 或更换新版本gcc
  • 谢谢,使用 malloc 效果很好!
  • @Zack 我之前尝试过,并使用 sprintf。但此时仅声明像char fileSizeStr[5] = ""; 这样的缓冲区或使用 malloc 有效。

标签: c arrays printf digits itoa


【解决方案1】:

您需要使用malloc 来分配动态内存量。

只有在编译时知道大小的情况下才允许以您的方式初始化。

【讨论】:

  • 谢谢!我不敢相信我完全忘记了使用 malloc。
【解决方案2】:

尝试类似:

 char* buffer =(char *)malloc(getDigits(number)*sizeof(char));

malloc 和 calloc 用于动态分配。

【讨论】:

  • 1.不要施放malloc。 2. 乘以sizeof (char) 没有意义,因为sizeof (char) 在C 中总是 1。
  • 哼,有趣。根据我刚刚搜索的内容,在这种情况下,在 C 中我们真的不必进行强制转换。但是 C++ 程序,我们可以......感谢您提供的信息!
【解决方案3】:

以下内容可能会有所帮助

char* buffer;
buffer = (char*)malloc(number * sizeof(char));

【讨论】:

  • 1.不要施放malloc。 2. 乘以sizeof (char) 没有意义,因为sizeof (char) 在C 中总是 1。
  • 为什么不强制转换 malloc?我认为只有在旧 C 中分配内存的方法。
  • @NigelHarper,我认为我写的是转换返回值。
  • @mmsc 是的,您正在转换 malloc 的返回值,由于我链接的答案中解释的原因,您不应该这样做。
【解决方案4】:

问题正是你的编译器告诉你的;您不允许初始化 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 可以用于任何类型的整数而无需修改:charshortintlonglong 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 的合适替代方案,这种情况很少见。

但是,如果您决定为此使用mallocfree,请以最不可怕的方式进行操作。避免对 malloc 的返回值进行类型转换和乘以 sizeof (char)(始终为 1)。以下代码是一个示例。使用上述任一方法计算长度:

char *buffer = malloc(digit_count(number)); /* Initialisation of malloc bytes not possible */
sprintf(buffer, "%d", number);

...完成后不要忘记free(buffer);

【讨论】:

    【解决方案5】:

    为了我的钱,有一个解决方案没有被提及,但实际上比上述任何一个都简单。在 Linux 和大多数 BSD 变体上都有一个名为“asprintf”的 sprintf 组合分配版本。它确定必要的大小,分配内存,并将填充的字符串返回到第一个参数中。

    char * a;
    asprintf(&a, "%d", 132);
    // use a
    free(a);
    

    使用堆栈分配的数组当然不需要释放空间,但这完全不需要单独计算大小。

    【讨论】:

    • 注意:在没有 asprintf 的系统上,使用 C99 很容易通过两次调用 snprintf 来实现自己的操作
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    相关资源
    最近更新 更多