5

C标准规定:

一个指向结构对象的指针,经过适当的转换,指向它的初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。

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

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

但是,C 标准规定:

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

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

标头.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);
}

主.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 结构main.c。它们可以被视为“在单独的翻译单元中声明的类型”吗?此外,它们真的满足所有其他兼容性要求,还是我误解了什么?

4

1 回答 1

2

What is a translation unit:

5.1.1.1 Program Structure

  1. A C program need not all be translated at the same time. The text of the program is kept in units called source files, (or preprocessing files) in this International Standard. A source file together with all the headers and source files included via the preprocessing directive #include is known as a preprocessing translation unit. After preprocessing, a preprocessing translation unit is called a translation unit.

So the c file plus the headers after preprocessing form a single translation unit. Let's take the translation unit which is made out of sep.c and header.h. It contains two declarations of the struct struct { int a; char b; }, one in the struct container and the other in the function print. Those structs are declared in the same translation unit.

6.2.7 Compatible type and composite type

  1. Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators. Moreover, two structure, union, or enumerated types declared in separate translation...

the remaining text is referring to types declared in separate translation units.

Since the structs are not declared in separate translation units, they do not fall under the 6.2.7 rule.

Therefore in my interpretation the structs, the one in struct container and the other in the cast in the print(), aren't compatible.

于 2015-01-13T16:46:38.717 回答