The C standard states:
A pointer to a structure object, suitably cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa.
Is there any possible (and well-defined) way to perform such a "suitable cast" in C11 if the first member of the struct in question is an anonymous struct/union? Or to perform the "vice versa" backward cast if the containing struct is anonymous?
I guess that casting to a non-anonymous struct with the same member sequence as the anonymous struct would make this not well-defined as they are not compatible, and, therefore, not guaranteed to have the same memory layout.
However, the C standard states:
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 <...>
Can we try to apply this rule to anonymous structs? Say, if we have the following setup:
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;
}
(this compiles on gcc (GCC) 4.8.3 20140911 and outputs 1).
Consider the anonymous struct used in the cast inside the print
function and the anonymous struct that is the first member of the struct container
that winds up in main.c
. Could they be considered "types declared in separate translation units"? Also, do they really satisfy all the other compatibility requirements, or am I misunderstanding something?
What is 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.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.