我的座右铭是在系统负载最小的情况下将一些虚拟数据写入文件。数据的大小是未知的,在运行时指定。
对于这个问题,我可以想到两个解决方案。
使用动态内存分配
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);
可变长度数组(VLA)是C99的标准特性,只要您知道您将使用的所有编译器都支持C99,就可以使用。然而,C11标准使可变长度数组成为可选的。即使在C99模式之外,gcc和clang也支持vla作为扩展。另一方面,Visual Studio
直到最近才支持C99,我认为他们还不支持VLA。
如果你事先不知道内存的大小,你可以选择通过malloc动态分配内存。
正如Jens所指出的,vla确实在堆栈上,如果数组的大小很大,堆栈空间有限,这可能是一个问题,如果是这种情况,那么你将不得不使用动态内存。
我想这样做:
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);
}
这完全避免了动态内存分配,并且可以很好地处理块大小
VLA有两个缺点
- 你不知道你可以在堆栈上为他们保留多少数据
- 如果分配不成功,没有错误返回。
因此,除非您确定您的数组永远不会超过若干kb的数据,否则我不会选择它们用于此目的。否则,如果分配失败,则会由于stackoverflow而出现虚假错误。