I'm trying to understand the implications of the following statement in the C99 standard (C99; ISO/IEC 9899:1999 6.5/7)
An object shall have its stored value accessed only by an lvalue expression that has one of the following types 73) or 88):
(other statements unrelated to question omitted)
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)
Consider the following:
typedef struct MyComplex {
float real;
float imag;
} MyComplex;
MyComplex *carray = malloc(sizeof(*carray) * 10);
float *as_floats = (float *)carray;
Is this legal since the MyComplex
structure contains a compatible float
type for the as_floats
pointer?
What about the other way around? i.e:
float *farray = malloc(sizeof(*farray) * 10);
MyComplex *as_complex = (MyComplex *)farray;
In both cases, ultimately, everything we're dealing with here is a float
, so maybe it's ok? I'm just not sure.
I ask, because I'm dealing with a legacy code base that does this kind of stuff all over the place and so far, everything seems fine. But I feel like we're playing with fire here. Trying to figure out if I need to disable strict aliasing on the compiler command line or not.
Note 13 in 6.7.2.1 of (I believe) all versions of the standard condones case #1 explicitly. You'll rarely get a clearer answer! My emphasis
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.
http://port70.net/~nsz/c/c99/n1256.html#6.7.2.1
YES! You can cast a structure to access its first member directly!
Why anyone thinks that's better than &(carray->real)
isn't clear. But it's definitely legit.
As another commenter pointed out I discussed case #2 in a previous question.
Aliasing Arrays through structs
It appears in conclusion that case #2 is an OK way to access the member real
.
Also iff the structure has no internal padding (platform dependent) you could even access the second member of the array through imag
.
I say platform dependent but other investigations have offered no known platform where such a structure would include padding.