【问题标题】:ISO C90 forbids variable length arrayISO C90 禁止变长数组
【发布时间】:2012-05-01 08:01:17
【问题描述】:

我正在动态计算数组的大小。比如:

void foo(size_t limit)
{
  char buffer[limit * 14 + 1];
}

但只是 GCC 编译器说:

error: ISO C90 forbids variable length array ‘buffer’

搜索所以我发现this answer:

C99 §6.7.5.2:

如果大小是一个不是整数常量的表达式 表达式... ...每次评估它都应该有一个值 大于零。

所以,我将大小限制类型变量重新声明为:

void foo(const size_t limit)

但它继续向我发出警告。这是 GCC 错误吗?

【问题讨论】:

  • 好吧,C90 != C99
  • size_t limit 声明为const 不会改变任何东西。它仍然是一个可变长度数组,因为大小是在运行时确定的。
  • GCC 告诉您,使用您使用的命令行选项,默认情况下它会根据 C90 标准进行编译。您引用的段落来自C99。这是您的问题的原因,而不是limit 的类型。
  • 应该注意的是,GCC 本身支持可变长度数组作为语言扩展,所以如果你不是在 c99 模式下编译,这将工作 - 但它不是可移植的,除非你总是使用一个编译器有这样的扩展或实现 C99 的 VLA。
  • 只需用gcc -std=c99 -pedantic ...调用gcc

标签: c variable-length-array


【解决方案1】:

C90 不允许变长数组。但是,您可以使用c99-gcc 编译器来完成这项工作。

您正在使用 c90-gcc 进行编译,但查看的是 C99 规范。

【讨论】:

    【解决方案2】:

    不,这不是错误。您不能在 C90 中使用 VLA。当你声明

    const size_t limit
    

    这不是一个常量表达式。常量表达式类似于文字值666

    请注意,C 在这方面与 C++ 有很大不同。甚至像这样的常量

    const int i = 666;
    

    在 C 中不是常量表达式。这就是为什么常量值在 C 中通常使用 #define 声明的主要原因。

    【讨论】:

    • 非常感谢您的解释。出于好奇,为什么 C90 标准不接受我尝试使用的常量表达式?因为如果我使用的是 const 类型,这意味着我以后不能修改它,那么,禁止它的原因是什么?和 C99 标准,否则, int 值不需要至少是 const 类型。对不起,我的英语不好。 :)
    • @Jack 你没有常量表达式。你有一个const 变量。常量表达式是 42 或 66。
    【解决方案3】:

    正如您在问题中所写,这是来自 C99,而不是 C90,您需要针对 C99 对其进行编译才能使用可变长度数组。

    【讨论】:

    • 或者您也可以使用alloca
    • 是的,但动态分配内存是另一回事。
    • alloca 和使用可变长度数组不是完全一样吗? (因为它使用堆栈内存而不是堆)
    【解决方案4】:

    const 在 C 中引入的不是常量而是只读变量。

    #define SIZE 16
    char bla[SIZE];   // not a variable length array, SIZE is a constant
    

    但是

    const int size = 16;
    char bla[size];   // C99 variable length array, size is a constant
    

    【讨论】:

      【解决方案5】:

      const 限定变量不是标准意义上的整数常量表达式。这必须是字面常量、枚举常量、sizeof 或由这些组成的某个表达式。

      如果可以,请切换到 C99。 gcc 选项是-std=c99(如果你想要 gnu 扩展,则为 gnu99。)

      【讨论】:

        【解决方案6】:

        const-限定变量不会使其成为编译时常量(请参阅 C99 6.6 §6 以了解 整数常量表达式的定义),并且在引入变量之前 - C99 的长度数组,数组大小需要是编译时常量。

        很明显,const-qualify 变量不会使其成为编译时常量,特别是在函数参数在调用函数之前不会被初始化的情况下。

        我看到以下解决您问题的方法:

        • 通过-std=c99-std=gnu99 将您的代码编译为C99
        • 通过malloc()分配缓冲区
        • 如果可用,请使用alloca(),这是您可以使用 C90 获得的最接近可变长度数组的方法
        • 选择一个始终使用的最大缓冲区大小,如果给定的limit 参数溢出则失败

        附带说明,即使 C99 允许可变长度数组,使用具有静态存储持续时间的整数变量的值作为具有静态存储持续时间的数组的大小仍然是非法的,无论 const-qualification 是什么:如果整数变量在同一个翻译单元中初始化,原则上没有什么可以阻止这一点,但您必须使用具有可见定义的特殊情况变量,这些变量的定义位于不同的翻译单元中,并且要么必须禁止暂定定义或者需要多次编译,因为在整个翻译单元被解析之前,临时定义的变量的初始化值是未知的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多