Is the following a standards-compliant C program (and by which standard(s))? If it is non-compliant (by breaking the strict aliasing rule or otherwise) is it "safe" with respect to GCC or any other commonly-used C compiler?
int main()
{
typedef struct {
int data;
} Type1;
typedef struct {
float data;
} Type2;
typedef struct {
Type1 type1;
Type2 type2;
} Aggregate;
Aggregate aggregate;
aggregate.type1.data = 1;
aggregate.type2.data = 2.0;
Aggregate *p_aggegregate = &aggregate;
Type1 *p_type1 = (Type1*) &aggregate;
Type2 *p_type2 = (Type2*) &aggregate;
int data1 = p_type1->data;
float data2 = p_type2->data;
return 0;
}
Strictly spoken, your program is standard compliant (C11, C99, dunno about K&R). It contains only pointer conversions and there are very little rules in the C standard which are restricting it
Your
Type1 *p_type1 = &aggregate;
Type2 *p_type2 = &aggregate;
breaks type safety and probably every compiler will warn about it as an invalid type conversion. But it is covered by
7 A pointer to an object type may be converted to a pointer to a different object type.
[6.3.2.3 "Pointers", C11 draft]
I have not found a rule which requires an explicit cast
Type1 *p_type1 = (Type1 *)&aggregate;
and paragraph above uses a similar wording like paragraph 1 one which allows the commonly used implicit something to/from void *
conversion.
Access to both variables is valid because &aggregate == &aggregate.type1
.
But as said, it is a really bad and unsafe style to write things in this manner and usual coding styles will consider this as an error. Access will be undefined when you add e.g. a char foo;
attribute before type1
.
EDIT:
Program is invalid; it violates
— the left operand has atomic, qualified, or unqualified pointer type, and [...] both operands are pointers to qualified or unqualified versions of compatible types [...]
[6.5.16.1 "Simple assignment"]
with
2 For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types. [6.7.6.1 "Pointer declarators"]