【问题标题】:Dynamic arrays in C without malloc?没有malloc的C中的动态数组?
【发布时间】: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]) 足够大,你可能无法逃脱!

标签: c variable-length-array


【解决方案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 操作数的一部分 运算符和更改大小表达式的值不会 影响算子的结果,是否影响不详 计算大小表达式。

    【讨论】:

      猜你喜欢
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 2013-10-13
      • 1970-01-01
      • 1970-01-01
      • 2020-08-17
      • 2016-04-06
      • 1970-01-01
      相关资源
      最近更新 更多