【问题标题】:Surprising completion of unknown array size typedef in C (gcc) to a known array size typeC(gcc)中未知数组大小typedef到已知数组大小类型的惊人完成
【发布时间】:2021-07-30 12:23:25
【问题描述】:

我遇到了一个有趣的情况——将一个不完整的数组大小 typedef 补全到一个已知的数组大小,例如:

#include <stdio.h>

typedef struct hi_
{
  int a, s;
} hi[];

int main() {
    hi there = { {3,7}, {1,5} };
    hi there2 = { {11,17} };

    printf("«1» 1/a: %i, 1/s: %i\n2/a:%i 2/s:%i\n", there[0].a, there[0].s, there[1].a, there[1].s);
    printf("«2» 1/a: %i, 1/s: %i\n", there2[0].a, there2[0].s);

// Output:
// «1» 1/a: 3, 1/s: 7
// 2/a:1 2/s:5
// «2» 1/a: 11, 1/s: 17

}

我有点惊讶,因为在this answer 中非常强烈地支持这种类型“无法完成”。那么,这是为什么以及如何工作的呢?

【问题讨论】:

  • 打个比方:int a[]= {1,2,3}; 声明了一个大小为 3 个整数的数组并对其进行初始化。您的代码也是如此。类型是完整的,只是类型定义中没有给出它的大小。

标签: arrays c incomplete-type completion


【解决方案1】:

问题中的typedef 将hi 定义为一个数组(大小未知)。

您引用的答案并不是说无法完成不完整的数组。它表示无法完成指向不完整数组的指针。它引用了标准:

...指向未知大小数组的指针类型,或由typedef 声明定义为未知大小数组的类型无法完成。

这里有一个语法错误(见下文,“of a type”应该是“to a type”),但答案说明了预期的含义:

阅读上下文,很明显“指向T 的未知边界数组的指针”不能“完成”为“指向N T 数组的指针”

语法错误是“由typedef 声明定义的类型为未知大小的数组”,“或”旨在替代“未知大小的数组”。因此,将“数组未知大小”替换为“类型……”将产生“由typedef 声明定义的类型的指针的类型是一个未知大小的数组……”所以“to of”是语法不正确,不是本意。

这句话可能是:

无法完成指向未知大小数组的指针类型或由typedef 定义为未知大小数组的类型。

至于为什么类型完成,C 2018 6.7.9 22 说:

如果一个未知大小的数组被初始化,它的大小由具有显式初始化器的最大索引元素确定。数组类型在其初始化列表的末尾完成。

因此,there 和 there2 是未知大小的数组(因为 hi 标识符是此类数组的别名),因此它们是通过初始化完成的。

如果您改为声明指向hi、hi *p; 的指针,那么即使进行初始化,也无法完成它。

【讨论】:

  • hi p[3]; 会完成数组但没有初始化?还是因为数组大括号是 typedef 的一部分而无效?
  • @PaulOgilvie: hi 是一个数组,所以hi something[3] 将是一个包含 3 个数组的数组。 (这违反了数组元素必须完整的规则,hi 不是。)
  • 所以除了通过初始化,没有办法指定hi的大小?
  • @PaulOgilvie:您可以分配内存并通过将一个写入内存来创建hi。根据 C 标准,这会在内存中创建该类型的对象。但是你不会有它的标识符,只有一个指向不完整的 hi 类型的指针。除了初始化之外,我想不出任何其他方法来指示大小。当然,不需要提供初始化器;你可以做hi there = { [99] = 0 };。
  • @PaulOgilvie:我想到了另一种方法。您可以使用hi 类型的最后一个成员定义结构。然后它是一个灵活的数组成员,它有空间允许的尽可能多的元素。所以这定义了大小。如果您创建一个具有自动或静态存储持续时间(而不是分配)的文件,编译器只会为结构分配其基本大小。这可能允许创建一些元素(由于其他结构元素引起的填充),但通常只会创建零个元素。在这种特殊情况下,数组的行为就像它只有一个元素,但您可能不会使用它(C 2018 6.7.2.1 18)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 2020-11-13
  • 1970-01-01
相关资源
最近更新 更多