C (gcc) 中未知数组大小 typedef 到已知数组大小类型的令人惊讶的完成

问题描述

我遇到了一个有趣的情况 - 将不完整的数组大小 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 中强烈支持无法完成”这样的类型。那么,为什么以及如何工作?

解决方法

问题中的 public Sheets getSheetsService() throws IOException,GeneralSecurityException { Credential credential = authorize(); return new Sheets.Builder(GoogleNetHttpTransport.newTrustedTransport(),JSON_FACTORY,credential) .build(); } typedef 定义为一个数组(大小未知)。

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

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

此处有语法错误(见下文,“of a type”应为“to a type”),但答案说明了预期含义:

结合上下文阅读,它清楚地表明“指向 typedef 未知边界数组的指针”不能“完成”为“指向 N T 数组的指针”

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

这句话可能是:

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

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

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

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

如果您改为声明一个指向 hi,hi 的指针,即使初始化,也无法完成它。