Arrays 将C(gcc)中未知的数组大小typedef意外地完成为已知的数组大小类型

Arrays 将C(gcc)中未知的数组大小typedef意外地完成为已知的数组大小类型,arrays,c,incomplete-type,completion,Arrays,C,Incomplete Type,Completion,我遇到了一个有趣的情况–将不完整的数组大小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", the

我遇到了一个有趣的情况–将不完整的数组大小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

}
#包括
类型定义结构hi_
{
INTA,s;
}嗨[];
int main(){
嗨,那里={3,7},{1,5};
hi-there2={11,17};
printf(“«1»1/a:%i,1/s:%i\n2/a:%i 2/s:%i\n”,那里[0].a,那里[0].s,那里[1].a,那里[1].s);
printf(“«2»1/a:%i,1/s:%i\n”,there2[0].a,there2[0].s);
//输出:
//«1»1/a:3,1/s:7
//2/a:1 2/s:5
//«2»1/a:11,1/s:17
}

我一点也不惊讶,因为在这个例子中,这种类型“无法完成””得到了非常强烈的支持。那么,为什么以及如何工作呢?

问题中的
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的指针,即使初始化也无法完成。

问题中的
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的指针,即使使用初始化也无法完成它。

作为类比:
inta[]={1,2,3}声明大小为3整数的数组并对其进行初始化。你的代码也是如此。类型是完整的,只是它的大小没有在typedef中给出声明大小为3整数的数组并对其进行初始化。你的代码也是如此。该类型是完整的,只是其大小未在typedef中给出。
hi p[3]是否将完成阵列,但不进行初始化?或者这是无效的,因为数组大括号是typedef的一部分?@PaulOgilvie:
hi
是一个数组,因此
hi something[3]
将是一个由3个数组组成的数组。(这违反了一条规则,即数组的元素必须是完整的,而
hi
不是完整的。)因此,除非通过初始化,否则无法指定
hi
的大小。@PaulOgilvie:您可以分配内存并通过将一个写入内存来创建
hi
。按照C标准,它在内存中创建了一个这种类型的对象。但是您没有它的标识符,只有一个指向不完整的
hi
类型的指针。我想不出任何办法