C11 - 将指针结构转换为struct的匿名第一个成员

Min*_*s97 5 c struct pointers c11 anonymous-struct

C标准规定:

指向结构对象的指针(适当地强制转换)指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.

如果所讨论的结构的第一个成员是匿名结构/联合,是否有任何可能的(和明确定义的)方法在C11中执行这样的"合适的强制转换"?或者,如果包含结构是匿名的,则执行"反之亦然"向后转换?

我想,使用与匿名结构相同的成员序列转换为非匿名结构将使得它不能很好地定义,因为它们不兼容,因此,不能保证具有相同的内存布局.

但是,C标准规定:

此外,如果它们的标记和成员满足以下要求,则在单独的转换单元中声明的两个结构,联合或枚举类型是兼容的:如果使用标记声明一个,则另一个应使用相同的标记声明.如果两者都在各自的翻译单元内的任何地方完成,则以下附加要求适用:其成员之间应存在一对一的对应关系<...>

我们可以尝试将此规则应用于匿名结构吗?比如说,如果我们有以下设置:

header.h:

struct container {
    struct {
        int a;
        char b;
    };
};

void print(struct container *pcontainer);
Run Code Online (Sandbox Code Playgroud)

sep.c:

#include <stdio.h>
#include "header.h"

void print(struct container *pcontainer){
    printf("%d\n", ((struct { int a; char b; }*)pcontainer)->a);
}
Run Code Online (Sandbox Code Playgroud)

main.c中:

#include "header.h"

int main(void){
    struct container container, *pcontainer;

    pcontainer = &container;
    pcontainer->a = 1;

    print(pcontainer);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(这在gcc(GCC)4.8.3 20140911编译,输出1).

考虑在内的铸造中使用的匿名结构print功能所述匿名结构是的第一构件struct container ,在卷起main.c.它们可以被视为"在单独的翻译单元中声明的类型"吗?此外,他们真的满足所有其他兼容性要求,还是我误解了什么?

250*_*501 2

什么是翻译单位:

5.1.1.1 程序结构

  1. AC程序不需要全部同时翻译。在本国际标准中,程序的文本保存在称为源文件(或预处理文件)的单元中。源文件以及通过预处理指令 #include 包含的所有标头和源文件一起称为预处理翻译单元。经过预处理后的预处理翻译单元称为翻译单元。

所以c文件加上预处理后的头文件就形成了一个翻译单元。让我们看一下由sep.cheader.h组成的翻译单元。它包含 struct 的两个声明struct { int a; char b; },一个在 struct 容器中,另一个在函数 print 中。这些结构在同一翻译单元中声明。

6.2.7 兼容型和复合型

  1. 如果两个类型的类型相同,则它们具有兼容类型。用于确定两种类型是否兼容的附加规则在 6.7.2(类型说明符)、6.7.3(类型限定符)和 6.7.6(声明符)中描述。此外,在单独的翻译中声明的两个结构、联合或枚举类型......

其余文本指的是在单独的翻译单元中声明的类型。

由于结构体未在单独的翻译单元中声明,因此它们不属于 6.2.7 规则的范围。

因此,根据我的解释,结构体(结构体容器中的一个结构体和 print() 中的强制转换中的另一个结构体)不兼容。

  • @Mints97:这是一个有趣的反对意见。sep.h 中的两个结构显然不兼容(如本答案所示),尽管它们似乎都与 main.c 中的结构兼容。我总是发现“兼容类型”关系不具有传递性这一事实有点不直观,但我从未想到过像这样的例子。 (2认同)