【问题标题】:const values in array dimensions [duplicate]数组维度中的常量值[重复]
【发布时间】:2017-03-20 07:35:21
【问题描述】:

下面的代码 sn-p 在 C 中工作和编译

const int n=10;
int main(void)
{
    int a[n];
    return 0;
}

但是,当数组在全局范围内声明时,会引发编译错误。

const int n=10;
int a[n];
int main(void)
{
    return 0;
}

有人可以解释为什么它不会在 main 中抛出错误。

【问题讨论】:

  • 它会抛出什么编译错误?

标签: c constants


【解决方案1】:

尽管 n 被标记为 const,但它不是编译时间常量1。因此数组a 是一个可变长度数组2

VLA 不能具有静态存储持续时间。将其放在文件范围内使其成为静态变量,因此您的程序格式错误3


  1. C11 N1570/6.6p6

    整数常量表达式117) 应具有整数类型,并且只能具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式、_Alignof 表达式和作为直接操作数的浮点常量的操作数的转换。整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为 sizeof 或 _Alignof 运算符的操作数的一部分。

  2. C11 N1570/6.7.6.2p4

    如果大小不存在,则数组类型是不完整类型。如果大小是 * 而不是表达式,则数组类型是未指定大小的可变长度数组类型,它只能用于具有函数原型范围的声明或类型名称;143) 这样的数组仍然是完整类型。 如果大小是整数常量表达式且元素类型具有已知的常量大小,则数组类型不是变长数组类型;否则,数组类型为变长数组类型

  3. C11 N1570/6.7.6.2p2

    如果一个标识符被声明为具有可变修改类型,它应该是一个普通标识符(如 6.2.3 中定义的),没有链接,并且具有块范围或函数原型范围。 如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型。

【讨论】:

  • 我认为,需要注意的是,VLA 不需要分配在堆栈上,它们也可以分配在堆上:int (*array)[foo] = malloc(sizeof(*array));。该限制是处理在 C 中没有定义全局/线程存储声明语句的执行顺序这一事实的显式限制。因此,对于全局变量,没有“此变量在此 VLA 声明语句中具有该值”的概念。
  • @cmaster - C 标准没有提到堆栈或堆,我也没有。我非常小心地坚持标准的措辞,即存储持续时间。跨度>
  • @cmaster 是一个(动态)分配的数组,由可变修改类型的指针指向。术语“VLA”是指自动数组
  • @M.M 这是对“VLA”一词的非常狭义的解释。 Afaik,C 标准主要不是在狭义上讨论 VLA(除了像这个答案中引用的特定例外),而是定义了“可变长度数组类型”是什么,并允许它们被使用得非常多可执行代码中的任何位置。您对 VLA 的具体含义只是一个更广泛概念的具体结果。
  • 换一种说法,你可以说所有 malloc 的空间都是具有运行时长度的数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 2021-10-27
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 2018-08-28
相关资源
最近更新 更多