没有malloc的C中的动态数组?

Posted

技术标签:

【中文标题】没有malloc的C中的动态数组?【英文标题】:Dynamic arrays in C without malloc? 【发布时间】:2011-10-03 03:48:56 【问题描述】:

我一直想知道如何才能摆脱这种情况:

int main(int argc, char **argv) 
    printf("%p %s %d\n", &argv[1], argv[1], strlen(argv[1]));
    char copy[strlen(argv[1]) + 1];
    strcpy(copy, argv[1]);
    printf("%p %s %d\n", &copy, copy, strlen(copy));
    return 0;

char 数组copy 无论如何都会被分配,程序运行良好,打印出原件和副本。 Valgrind 没有抱怨任何事情。

我认为在没有 malloc 的情况下,动态数组在 C 中是不可能的。我错了吗?

【问题讨论】:

"dynamic" == "resizable",不一定是"编译时常量"。 C99 介绍了这个。 如果 strlen(argv[1]) 足够大,你可能无法逃脱! 【参考方案1】:

这是一个 C99 功能,可以在 prior versions by the compiler 上实现。

在 ISO C99 中允许使用可变长度自动数组,并作为 扩展 GCC 在 C90 模式和 C++ 中接受它们。这些数组是 像任何其他自动数组一样声明,但长度为 不是常量表达式。存储在点分配 退出大括号级别时声明和释放。

【讨论】:

【参考方案2】:

可变长度数组起源于GCC extension,但也被C99采用。

它们仍在堆栈上分配,因此将它们设置为“巨大”被认为是不好的风格(并且可能有一天会破坏你)。

【讨论】:

哇。我已经很久没有使用纯 C(或 gcc)了,我完全错过了这个成为标准的东西。 @Dima:说实话,我忘记了自己,直到我重新阅读了 GCC 手册中的描述:-)。 (我从不使用此功能;使用动态堆栈太危险了。) @Nemo:只要您知道目标平台上的堆栈限制并将其考虑在内,我认为这并不危险。 @Stephen:根据我的经验,代码总是比“目标平台”更长寿。 (换句话说,最终的目标平台永远不会像你想象的那样出名。)还有很棒的静态检查器 (Coverity) 可以计算程序 total 堆栈消耗的界限,但可能不存在这样的东西。所以总的来说,我认为最好避免使用这个小工具。 (当然每条规则都有例外。) 我同意你的两个论点;我经常使用递归来实现既简单又方便的解决方案,但大型不确定堆栈模式当然需要额外考虑。【参考方案3】:

甚至在“可变长度数组”出现之前,由 gcc 和 C99 提供,就有:

alloca() -- 允许动态分配堆栈(“自动”)内存。

【讨论】:

根据 alloca 的 BSD 手册页,它是在 32V AT&T Unix (1979) 中引入的。所以它已经有一段时间了。 alloca is evil 在分配可能大量的内存时。 @Vorac -- 感谢您的意见,但事实并非如此。你亲自尝试过吗?程序通常可用的堆栈数量远远超过“几百字节”。显然,我们总是需要注意机器的限制,但是假设 alloca() 更有限,sbrk() 并没有多大意义,真的。【参考方案4】:

“可变长度数组”在 C99 中被添加到 C 语言中。这在第 6.7.5.2 节“数组声明符”中有所介绍:

如果大小是一个不是整数常量的表达式 表达式:如果它出现在函数原型范围的声明中, 它被视为被 * 替换;否则,每次都是 评估它的值应大于零。每个的大小 可变长度数组类型的实例在其期间不会改变 寿命。其中大小表达式是 sizeof 操作数的一部分 运算符和更改大小表达式的值不会 影响算子的结果,是否影响不详 计算大小表达式。

【讨论】:

以上是关于没有malloc的C中的动态数组?的主要内容,如果未能解决你的问题,请参考以下文章

剖析C动态内存管理 (malloc,calloc,realloc,柔性数组)

C语言里,啥时候用数组啥时候用指针和动态内存(malloc/calloc)?

如何定义一个动态的数组

C++ New vs Malloc 用于对象的动态内存数组

C语言 如何给指针数组划分动态存储空间

c语言动态数组如何扩充空间