指向不完整类型的指针可以不完整吗?

Posted

技术标签:

【中文标题】指向不完整类型的指针可以不完整吗?【英文标题】:Can a pointer to an incomplete type be incomplete? 【发布时间】:2020-04-30 15:27:14 【问题描述】:

int (*)[] 可以是不完整类型吗?

C 2018 6.2.5 1 说:

在翻译单元内的不同点,对象类型可能是不完整(缺乏足够的信息来确定该类型对象的大小)或完整(有足够的信息)。

因此,如果类型的大小已知,则该类型似乎是完整的。 6.2.6.1 28 指定某些类型的指针必须具有相同的大小(指向void 和字符的指针、指向兼容类型的指针、指向结构的指针和指向联合的指针),但指向其他类型的指针可能会有所不同。

在所有指针或指向int 数组的所有指针具有相同大小的C 实现中,那么int (*)[] 的大小是已知的,因此它是完整的。在一个实现中,比如说,对大数组使用不同的指针,大小是未知的,所以它是不完整的。

作为M.M points out,根据 6.7.2.1 3 中的约束,结构不得包含类型不完整的成员,最终灵活数组成员除外。这表明具有一种指针大小的实现必须接受struct int (*p)[]; 而对于此类数组具有不同大小的实现必须诊断违反约束。 (这反过来又意味着这样的声明不是严格符合 C 的一部分。)

【问题讨论】:

6.2.5(p22) 帮助? (或者它是否增加了更多的混乱,允许稍后声明完成不完整的类型?) @DavidC.Rankin 在 6.2.5/20 中甚至说指针总是完整的类型 @LanguageLawyer:这有什么关系?问题是“有一个不是 Y 的 X 吗?”,而不是“有一个不是 Y 的 X 吗?” @LanguageLawyer:void * 是完整的事实表明指向不完整类型的指针可以是完整的。它没有显示指向不完整类型的指针是否不完整。如果有人问“哺乳动物可以是大象吗?”,表明“狮子是哺乳动物”并不能说明哺乳动物不能是大象。该问题询问指向不完整类型的指针集合 X 是否可能包含不完整的元素。表明指向不完整类型的指针集合 X 包含完整的元素是无关紧要的。 @EricPostpischil 哎呀。我把标题误读为“指向不完整类型的指针可以完整吗?” 【参考方案1】:

未知大小的数组不完整:

未知大小的数组类型是不完整类型。对于该类型的标识符,它是通过在以后的声明中指定大小来完成的(使用内部或外部链接)。

int (*)[] 类型并不完整:它是大小未知的int 数组的指针。 并且指针具有众所周知的大小:

printf ("Size %d\n", sizeof(int (*)[]));

6.2.5/23:如果类型不完整且不是可变长度数组类型,则该类型具有已知的常量大小。

此外,由于数组语义,您甚至可以取消引用它:

typedef int (*T)[];
...
int a[10];
for (int i=0; i<10; i++) a[i]=i;
T p=a;
for (int i=0; i<10; i++) printf ("%d ",(*p)[i]);
printf ("\n");

编辑

此外,指针始终是完整类型。它在 6.2.5/20 中被黑底白字:

指针类型可以派生自函数类型或对象类型, 称为引用类型。指针类型描述了一个对象,其 value 提供对被引用类型的实体的引用。一种 从引用类型 T 派生的指针类型有时称为 “指向 T 的指针”。从被引用的指针类型的构造 类型称为“指针类型派生”。 指针类型是 完整的对象类型。

【讨论】:

我认为你已经把它归结为 gcc 同意。 struct w/pointer to incomplete array 类似于引发讨论的原始问题。 只有最后一段是相关的。示例printf 仅显示指向不完整数组的指针在执行它的实现中是完整的,如问题中所述 - 如果不是上一段中引用的 6.2.5 20,它可能无法编译。 6.2.5 23 也不相关;它告诉我们大小是已知的并且如果它是完整的并且是恒定的,并且我们已经知道完整意味着大小是已知的。 6.2.5 20 很有趣。我推测它不打算产生这种结果,但这意味着在不完整时具有相同类型的完整类型的所有指针必须具有相同的大小。例如,所有指向int 数组的指针必须具有相同的大小,并且所有指向某个struct 数组的指针必须具有相同的大小,尽管可能并非所有指向不同类型数组的指针struct 的大小必须相同。 @EricPostpischil 可能是文本“同样,指向兼容类型的合格或非合格版本的指针应具有相同的表示和对齐要求。”应该解释为T(*)[] 必须与T(*)[5] 具有相同的大小,因为它们是兼容的类型,我们可以添加或删除限定符 允许兼容类型具有不同的大小会导致一大堆问题,这可能是标准没有明确排除它的缺陷

以上是关于指向不完整类型的指针可以不完整吗?的主要内容,如果未能解决你的问题,请参考以下文章

c++mfc为何报错不允许指针指向不完整的类类型?

指向不完整类型成员函数的指针

使用 strcmp 取消引用指向不完整类型错误的指针 [关闭]

取消引用指向不完整类型的指针

取消引用指向不完整类型的指针

C错误 - 取消引用指向不完整类型的指针