C中可变大小的数组。可以吗?

时间:2014-03-12 11:50:36

标签: c arrays file file-io

我的座右铭是在系统中以最小的负载将一些虚拟数据写入文件。数据的大小未知并在运行时指定。

为此我可以想到2个解决方案。

1)使用动态内存分配

reserve_size_in_file (int reserve_size, FILE *fp) 
{
    char *p
    p = malloc(reserve_size)
    fwrite(p, sizeof(*p), 1, fp);
    free(p);
}

2)使用数组

reserve_size_in_file (int reserve_size, FILE *fp) 
{
    char arr[reserve_size];
    fwrite(arr, sizeof(arr), 1, fp);
}

我认为第二种方法不能用于声明一个长度可变的数组(ewww ...),我认为是不允许的。但它正在发挥作用。现在我的问题是,可以这样使用它吗?此外,如果有另一种更好的方法,请建议。

注意:我无法使用fallocate(),因为我只需处理流IO。

修改:

我刚看到我可以使用fileno(fp)并使用fallocate()。但是我没有看到很多使用fallocate()的应用程序。使用fallocate()

是否有任何问题

例如:fallocate(fileno(fp), 0, 0, 100000);

3 个答案:

答案 0 :(得分:3)

Variable length arrays VLA )是C99标准功能,只要您知道将使用支持C99的所有编译器,就可以使用它。 C11标准虽然可变长度数组可选。 gccclang都支持VGA甚至在C99模式之外作为扩展。另一方面,Visual Studio直到最近才支持C99,我认为它们还不支持VLA。

如果您不知道提前的大小,可以选择通过malloc进行动态内存分配。

正如Jens所指出的,如果数组的大小很大,那么VLA会进入堆栈并且你有limited stack space这可能是一个问题,如果是这种情况,那么你将不得不使用动态内存。

答案 1 :(得分:2)

VLA有两个缺点

  • 你不知道你可以在堆栈上保留多少数据""对他们来说
  • 如果分配没有成功,则没有错误返回。

因此,除非您确定您的阵列永远不会超过一些数据,否则我不会为此选择它们。否则,如果分配失败,您将因堆栈溢出而出现虚假错误。

答案 2 :(得分:2)

我这样做:

reserve_size_in_file (int reserve_size, FILE *fp) 
{
    /* Usual HDDs have a block size of 512, but big
     * block storage is becoming popular. */
    char arr[4096]; 

    /* initialize to 0xff, since runs of NUL bytes might
     * be transparently replaced with sparse file holes. */
    memset(arr, 0xff, sizeof(arr));

    while(reserve_size > sizeof(arr)) {
        fwrite(arr, sizeof(arr), 1, fp);
        reserve_size -= sizeof(arr);
    }
    fwrite(arr, reserve_size, 1, fp);
}

这完全避免了动态内存分配,并且可以很好地处理块大小。