Reading from different union members

Discussion in 'C Programming' started by Johannes Schaub (litb), Dec 30, 2009.

  1. 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
    not be undefined behavior:

    union A a;
    a.b = 3.1f;
    int c = a.a;

    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".

    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;

    What am i missing? Is this reading from an lvalue of "an aggregate or union
    type that includes one of the aforementioned types among its members"? I
    can't think of a way this would be true, since the lvalue used in the above
    is "a.a", and it definitely has not the type "union A", but the type "int" -
    the same type that the lvalue "*pc" has - so why is the one undefined, and
    the other not!?

    Any hints, please? Thanks!
    Johannes Schaub (litb), Dec 30, 2009
    #1
    1. Advertising

  2. On 30 Dec, 01:33, "Johannes Schaub (litb)" <>
    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.


    you can onlyassume this for a particular implementation

    >Then, i read


    read where?

    > that we are allowed to do the following, and it would
    > not be undefined behavior:
    >
    > union A a;
    > a.b = 3.1f;
    > int c = a.a;


    I think this is UB

    > 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".


    hence it's UB

    > 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;
    >
    > What am i missing? Is this reading from an lvalue of "an aggregate or union
    > type that includes one of the aforementioned types among its members"? I
    > can't think of a way this would be true, since the lvalue used in the above
    > is "a.a", and it definitely has not the type "union A", but the type "int" -
    > the same type that the lvalue "*pc" has - so why is the one undefined, and
    > the other not!?
    >
    > Any hints, please? Thanks!
    Nick Keighley, Dec 30, 2009
    #2
    1. Advertising

  3. Johannes Schaub (litb)

    Kaz Kylheku Guest

    On 2009-12-30, Johannes Schaub (litb) <> 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.
    Kaz Kylheku, Dec 31, 2009
    #3
  4. Kaz Kylheku <> writes:
    <snip>
    > However, an unspecified value may be a trap representation.


    3.17.3 p2 contradicts this explicitly. I am not sure what effect that
    has on the rest of your argument but I think it may be significant.

    <snip>
    --
    Ben.
    Ben Bacarisse, Dec 31, 2009
    #4
  5. Johannes Schaub (litb)

    Tim Rentsch Guest

    "Johannes Schaub (litb)" <> writes:

    > 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
    > not be undefined behavior:
    >
    > union A a;
    > a.b = 3.1f;
    > int c = a.a;
    >
    > 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 object designated by a.a has effective type "int", because 'a'
    is declared as a (union A), and member 'a' of (union A) is declared
    as (int).
    Tim Rentsch, Jan 13, 2010
    #5
  6. Johannes Schaub (litb)

    Tim Rentsch Guest

    Kaz Kylheku <> writes:

    > On 2009-12-30, Johannes Schaub (litb) <> 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.


    Sure we can. The assumptions limit the set of implementations
    under consideration, but it's still standard C, just not
    every conceivable implementation of standard C.


    >> 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).


    It's only the bytes that don't correspond to the object being
    assigned that take unspecified values. Under the stated
    assumptions there are no such bytes.


    > However, an unspecified value may be a trap representation.


    Again, under the assumptions stated no such trap representations
    exist.
    Tim Rentsch, Jan 13, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt Garman
    Replies:
    1
    Views:
    652
    Matt Garman
    Apr 25, 2004
  2. Denis Remezov

    Address of union members

    Denis Remezov, Jun 30, 2004, in forum: C++
    Replies:
    6
    Views:
    373
    Mike Wahler
    Jul 1, 2004
  3. Frederico Faria

    union ( members with same name )

    Frederico Faria, Jul 4, 2003, in forum: C Programming
    Replies:
    4
    Views:
    618
    Frederico Faria
    Jul 8, 2003
  4. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    854
    Chris Torek
    Apr 26, 2004
  5. pozz
    Replies:
    2
    Views:
    239
Loading...

Share This Page