Keith Thompson wrote:
Keith Thompson wrote:
Ben Pfaff wrote:
Why is it legal to do
union U {unsigned char u[8]; int a;};
union U u;
u.a = 1;
u.u[0];
See C99 section 6.5 "Expressions":
An object shall have its stored value accessed only by an
lvalue expression that has one of the following types:73)
[...]
- a character type.
But character type is not a union.
[snip]
u.a is of type int. u.u[0] is of type char, a character type. The
code above accesses the stored value of the object u.a using an lvalue
expression, u.u[0], which is of character type, which satisfies 6.5.
I am not convinced. Consider this:
int a;
int b;
int *p = &b;
*(p - 1);
It accesses value of a using an lvalue of type int. The problem is
of course that *(p-1) is illegal.
Another problem is that it's not necessarily accessing the value of
a.
Well, UB here is totally enough for me, regardless of what exactly
implementation will do
However, the standard does explicitly allow objects to be adjacent (it
has to do so to make pointer equality work consistently). In the
absence of any knowledge of how a and b are allocated in memory,
evaluating *(p - 1) invokes undefined behavior. If you happen to know
that they're adjacent, then *(p - 1) does access the value of a, and
it's legitimate (though quite silly).
It's legitimate? Pointer arithmetic is allowed only on arrays (not sure
what correct term is, it's not those int a[2]; arrays), isn't it? I
mean, it's UB even if a and b happen to be adjacent (which itself
isn't a standard term, since standard doesn't know what it means for
objects which are not members of some aggregate, in which case we
can talk about sequences of bytes).
For purposes of pointer arithmetic, any object can be treated as if it
were a single-element array. See, for example, C99 6.5.8p4:
....
Without this special-case permission, the standard would have had to
say that, given
int a;
int b;
&a + 1 *may not* be equal to &b (or vice versa), which would require
the implementation to insert at least one byte of padding between
objects that might otherwise be adjacent.