E
Eric Sosman
It does!
I know it seems weird, but it makes sense to me, because this is exactly
what you have to have be true for the optimizer to be able to make informed
decisions about whether a write to one thing can alter another thing.
Consider, given the above:
unsigned char *p1 = (unsigned char *) &fa;
unsigned char *p2 = (unsigned char *) &fa.x;
unsigned char *p3 = (unsigned char *) &fa.y;
It's *useful* to be assured that a write through p2 can't legitimately alter
the contents of p3. It's not a pointer into the whole struct, just into one
member of it. But you have to be able to indicate that sometimes you really
do mean you want to write through the pointer, thus p1 has to work.
One more pathetic bleat, and then I'll stop whimpering ...
If p2's only legitimate targets are limited to the bytes of
fa.x (and not all of fa), and if that limitation remains in effect
even when p2's value is converted to another type (void* in the
earlier example), then what are we to make of 6.7.2.1p15? It tells
us that a pointer to fa's first element can be converted to a pointer
to fa. But if a pointer derived from &fa.x can only be used to
access the constituent bytes of fa.x, is conversion to a struct
pointer useful? That is, does
((struct foo *) p2)->y = 27;
have undefined behavior?