【问题标题】:How is an array of size 0 stored in memory?大小为 0 的数组如何存储在内存中?
【发布时间】:2019-02-03 14:27:02
【问题描述】:

如果我有一个只有一个元素的数组,我们可以说它与指针相同。 但是一个大小为零的数组在内存中是如何表示的呢?

当我声明一个变量 int * table[0] 时会发生什么?

【问题讨论】:

  • 如何计算一个元素为零的数组的大小?
  • 注意zero length arrays are undefined behavior 虽然支持作为扩展,但这个特殊用例似乎没有用。
  • 只有 GCC(和模拟 GCC 的 Clang)允许零大小的数组。 C 标准不允许它们。

标签: c arrays pointers memory


【解决方案1】:

C 标准在技术上不支持零长度数组。但是,一些编译器(例如 gcc)允许它们作为扩展。

它们是 C99 之前创建灵活数组成员的方法,如下所示:

typedef struct {
    int len;
    int contents[0];
} arr;

然后,您可以在最后为数组初始化尽可能多的空间:

arr* a = malloc(sizeof(*a) + sizeof(a->contents) * 10); /* for a length-10 array */
a->len = 10;

【讨论】:

  • int contents[]; 将是一个灵活的数组成员int contents[0]; 不是 FAM。
  • 我同意,这里的一致性更好。经过更多的研究,它们似乎更像是一个历史扩展,现在被灵活的数组成员淘汰了。
【解决方案2】:

如果我有一个只有一个元素的数组,我们可以说它与 指针

不,我们不能。数组和指针是不同的类型,它们在内部的表示方式也不同。无论数组大小如何,这都是正确的。现在,在某些情况下(实际上是大多数情况),数组衰减到指向它的第一个元素的指针也是正确的。

按照标准,大小为 0 的数组是非法的,但是一些主要的编译器(如 gcc)允许它们作为扩展。

阅读此问题以了解数组和指针的内部表示之间的区别:Difference between dereferencing pointer and accessing array elements

【讨论】:

    【解决方案3】:

    严格来说,数组的大小不允许为 0。这在C standard 的第 6.7.6.2p1 节中有规定:

    除了可选的类型限定符和关键字 static 之外,[ 和 ] 可以分隔表达式或 * .如果它们分隔了一个表达式(它指定了一个数组的大小),则该表达式应为整数类型。 如果表达式 是一个常量表达式,它的值应该大于零。 元素类型不应是不完整类型或函数类型。这 可选类型限定符和关键字 static 应出现 仅在带有数组的函数参数声明中 类型,然后只在最外层的数组类型推导

    一些编译器确实支持这个作为扩展,例如GCC:

    在 GNU C 中允许将零长​​度数组声明为扩展。一种 零长度数组可用作结构的最后一个元素 这实际上是可变长度对象的标头:

    struct line {
      int length;
      char contents[0];
    };
    
    struct line *thisline = (struct line *)
      malloc (sizeof (struct line) + this_length);
    thisline->length = this_length;
    

    虽然零长度数组的大小为零,但数组成员 由于以下原因,这种类型可能会增加封闭类型的大小 尾部填充。零长度数组成员的偏移量 封闭结构的开头与 具有一个或多个相同类型元素的数组。一个对齐 零长度数组与其元素的对齐方式相同。

    【讨论】:

      猜你喜欢
      • 2019-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 2012-05-28
      • 2012-06-28
      相关资源
      最近更新 更多