On 2009-12-30, Johannes Schaub (litb) <schaub-> wrote:
> Hello all. What makes these two codes different:
>
> union A {
> int a;
> float b;
> };
>
> Let's assume int has no trap representations, and size of an int is that of
> a float. Then, i read that we are allowed to do the following, and it would
We can't make these constraining assumptions and still be talking about
the standard language at the same time.
> not be undefined behavior:
>
> union A a;
> a.b = 3.1f;
> int c = a.a;
This situation is explicitly listed in Informative Annex J of C99
(J.1 Unspecified Behavior). This points back to 6.2.6.1 (where paragraph
7 is most relevant).
However, an unspecified value may be a trap representation.
6.2.6.1/7 only tells us that the union as a whole doesn't become
a trap representation.
I.e. the above usage is not well-defined in the ISO C dialect,
though we are able to characterize specific kinds of implementations
where it will have non-failing semantics, because the unspecified
behavior is chosen such that there is no trap rep. We can expect
a certain consistency. An implementation cannot document that the
int type has no trap representation, and then fail the above a.a access.
> But why is this? 6.5/7 says that we are not allowed to read the value of an
> object having effective type "float" by an lvalue having type "int".
The effective type of the object a.a is int. a.a is declared, and for
declared objects, effective type is declared type.
6.5 doesn't resolve the union issue.
> Contrary, if i do the following, some sources i read say that behavior is
> undefined for the above reason. However what makes this case different?
>
> int *pc = &a.a;
> int c = *pc;
Nothing. This is also unspecified. This still accesses a union member,
using an lvalue which matches its effective (i.e. declared) type,
meeting the requirements of 6.5.
It is the value of a.a that is unspecified after assignment to a.b,
irrespective of how a.a is accessed.
> Is this reading from an lvalue of "an aggregate or union
> type that includes one of the aforementioned types among its members"? I
No. This is reading an int, not a union itself.
The purpose of the above text is to allow members to be manipulated
through their containing aggregates (possibly through multiple levels
of nested aggregation).
When we are, say, assigning a struct of type struct foo which contains an int
member, then you are in fact accessing that int member other than
through an lvalue of type int! The text clarifies that it is okay to
do this when the accessing lvalue is to the containing aggregate.
|