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

时间:2015-01-13 16:37:20

标签: c pointers struct c11 anonymous-struct

C标准规定:

  

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

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

我想,使用与匿名结构相同的成员序列转换为非匿名结构会使其定义不明确,因为它们不兼容,因此,不能保证具有相同的内存布局。

然而,C标准规定:

  

而且,两个结构,   union或在单独的翻译单元中声明的枚举类型如果它们是相容的   标签和成员满足以下要求:如果使用标签声明一个,则   其他声明应使用相同的标签声明。如果两者都在他们的任何地方完成   各个翻译单位,则适用以下附加要求:应有   是其成员之间的一对一对应< ...>

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

header.h:

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

void print(struct container *pcontainer);

sep.c:

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

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

main.c中:

#include "header.h"

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

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

    print(pcontainer);

    return 0;
}

(编译于 gcc(GCC)4.8.3 20140911 并输出1)。

考虑在print函数中的强制转换中使用的匿名结构和作为struct container 的第一个成员的匿名结构{ {1}} 的。它们可以被视为“在单独的翻译单元中声明的类型”吗?另外,他们真的满足所有其他兼容性要求,还是我误解了什么?

1 个答案:

答案 0 :(得分:2)

什么是翻译单位:

  

5.1.1.1程序结构

     
      
  1. C程序不需要同时翻译。保留了该程序的文本   在本国际标准中称为源文件(或预处理文件)的单元中。 甲   源文件以及通过预处理包含的所有头文件和源文件   指令#include被称为预处理转换单元。预处理后,a   预处理翻译单元称为翻译单元。
  2.   

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

  

6.2.7兼容类型和复合类型

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

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

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

因此,在我的解释中,结构容器中的结构体,以及print()中的结构体中的结构体是不兼容的。