You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无标签结构体重声明是否为兼容类型?C标准合规分析

无标签结构体重声明的类型兼容性问题

咱们直接聚焦核心问题:无标签结构体的重声明是否属于兼容类型?

为了验证这个问题,我写了一段测试代码来探究类型转换的合法性:

typedef struct { int a; } A;
typedef struct { struct { int a; }; int b; } B;
A *BToA(B *b) { return (A *) b; }
B *AToB(A *a) { return (B *) a; }

我们原本期望这段代码里的类型转换符合C 2011标准的6.7.2.1 第15条款

指向结构体对象的指针经适当转换后,指向其初始成员(若该成员为位域,则指向其所在的存储单元),反之亦然。

这里需要明确:B内部的那个无标签结构体struct { int a; }我们暂时称它为A'

不过标准里并没有明确定义“适当转换”的具体范围。我们可以先做个假设:如果b是指向A'类型对象的有效指针,那么(A *) b属于适当转换;同理,如果a是指向B中A'的指针,(B *) a也属于适当转换。但这就引出了更关键的问题:A *是否为指向A'类型对象的有效指针?

我们可以结合C标准的条款一步步推导:

  1. 根据6.7.6.1条款:如果类型AA'兼容,那么指针类型A *A' *就是兼容的。
  2. 再看6.2.7条款对兼容类型的定义:

    若两种类型相同,则它们属于兼容类型……此外,在不同翻译单元中声明的两个结构体、联合体或枚举类型,若其标签和成员满足以下要求则兼容:若其中一个带有标签,另一个必须带有相同标签;若两者在各自翻译单元中均已完成声明,则需满足额外要求:成员需一一对应,每对对应成员的类型兼容;若某成员带有对齐说明符,另一成员需带有等效的对齐说明符;若某成员带有名称,另一成员需带有相同名称;对于结构体,对应成员的声明顺序需一致……

  3. 6.7.2.3 第5条款明确规定:

    每个未包含标签的结构体、联合体或枚举类型声明,均表示一种不同的类型

由此可知,AA'并非同一类型——因为它们是同一翻译单元里的两个无标签结构体声明。那它们是否属于兼容类型呢?6.2.7条款里提到的兼容情况仅针对不同翻译单元中的结构体,而本例中两者在同一个翻译单元内,所以完全不满足兼容的条件。

总结下来:同一翻译单元内的无标签结构体声明都是独立的不同类型,彼此不兼容。因此A *A' *也不兼容,之前代码里的类型转换是否符合标准中的“适当转换”并没有明确的合法性保障。

内容的提问来源于stack exchange,提问作者Eric Postpischil

火山引擎 最新活动