Search code examples
clanguage-lawyerstandards

Are identical anonymous structures compatible?


Consider this code snippet:

#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;
}

Regarding the casting of a void * to struct { int; int } *, assuming that the fields of the anonymous structure are identical to the fields of the structure that was initially allocated, is this well defined behavior according to the C standard?


Solution

  • These structs would be compatible if they were not in the same file.

    Had thread_start been defined in a separately compiled .c file (i.e. a separate translation unit) then they would be compatible. Specifically, the names, types, and order of the members are the same, and they both have the same tag which in this case is no tag.

    Section §6.2.7 ¶1 of the C standard lays out these requirements:

    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.

    So these structs would be compatible if they were not in the same file. But because they are, the structs are not compatible.

    §6.7.2.1 ¶8 says:

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

    So, §6.7.2.1 specifies what happens in a single translation unit. The specification in §6.2.7 overrides the specification in §6.7.2.1 when the declarations are in separate translation units.

    NB: It's easy to confuse 6.2.7 and 6.7.2.