I'd like to be able to do something like...
typedef struct{
int type;
}foo_t;
foo_t *foo = foo_init();
*(int*)foo = 1;
or
typedef struct{
int type;
}bar_t;
typedef struct{
bar_t header;
}foo_t;
foo_t *foo = foo_init();
((bar_t*)foo)->type = 1;
...do one or both of these violate C's strict aliasing rule? The latter seems more common and I wasn't sure if that was because of it's cleaner syntax or if the extra struct was necessary to get around strict aliasing.
CodePudding user response:
Both are valid.
A pointer to a struct may be safely converted to a pointer to its first member. You're doing this in both cases.
This is specified in section 6.7.2.1p15 of the C standard regarding structure and union specifiers:
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
CodePudding user response:
For initial fields and as cast the effect is correct. However
foo->type = 1;
foo->header.type = 1;
both will give the same optimal code, so you are just obfuscating your own code, eliminating type checking.
If one would put the casted address in a variable, then that would be an alias, and changes to either the original or aliasing variable could be wrongly optimized, go undetected.
That is not the case here as the cast uses the original variable.
Conclusion: not a case of strict antialiasing, but to be avoided because unsafe = correctness not guaranteed by the compiler.