相同的匿名结构是否兼容?

Are identical anonymous structures compatible?

考虑这个代码片段:

#include <threads.h>

int thread_start(void *ptr)
{
    struct {
        int a;
        int b;
    } *data = ptr;

    return 0;
}

int main(int argc, char *argv[])
{
    struct {
        int a;
        int b;
    } data;

    thrd_t thread;
    thrd_create(&thread, thread_start, &data);
    thrd_join(thread, NULL);
    return 0;
}

关于将 void * 转换为 struct { int; int } *,假设匿名结构的字段与最初分配的结构的字段相同,根据C 标准?

如果这些结构不在同一个文件中,它们将是兼容的。

如果 thread_start 在单独编译的 .c 文件中定义(即单独的 翻译单元 ),那么它们将是兼容的。具体来说,成员的名称、类型和顺序都是相同的,并且它们都有相同的标签,在这种情况下是没有标签。

§6.2.7 ¶1 of the C standard 部分列出了这些要求:

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 units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are completed anywhere within their respective translation units, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types; if one member of the pair is declared with an alignment specifier, the other is declared with an equivalent alignment specifier; and if one member of the pair is declared with a name, the other is declared with the same name. For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values.

因此,如果这些结构 不在同一个文件中,它们将 兼容。但是因为它们是,所以结构不兼容。

§6.7.2.1 ¶8 说:

The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.

因此,§6.7.2.1 指定了单个翻译单元中发生的情况。当声明位于单独的翻译单元中时,§6.2.7 中的规范将覆盖 §6.7.2.1 中的规范。

注意:很容易混淆 6.2.7 和 6.7.2。