union field access

Discussion in 'C Programming' started by Edward Rutherford, May 27, 2011.

  1. If I have an union

    union U {
    struct X x;
    struct Y y;
    struct Z z;

    } u;

    and both struct Y and struct Z have a struct X as the first field, then
    can I always access u.x.<field> even if I am actually putting a struct Y
    or Z in u?
     
    Edward Rutherford, May 27, 2011
    #1
    1. Advertising

  2. Edward Rutherford

    Shao Miller Guest

    On 5/27/2011 16:58, Edward Rutherford wrote:
    > If I have an union
    >
    > union U {
    > struct X x;
    > struct Y y;
    > struct Z z;
    >
    > } u;
    >
    > and both struct Y and struct Z have a struct X as the first field, then
    > can I always access u.x.<field> even if I am actually putting a struct Y
    > or Z in u?


    Yes. It's called "type punning," if I'm not mistaken.

    "82) If the member used to access the contents of a union object is not
    the same as the member last used to store a value in the object, the
    appropriate part of the object representation of the value is
    reinterpreted as an object representation in the new type as described
    in 6.2.6 (a process sometimes called "type punning"). This might be a
    trap representation."

    It also means that you if you have a function like:

    void some_func(struct X * x);

    You can pass your union object with something like:

    union U u;
    some_func(&u.x);
     
    Shao Miller, May 27, 2011
    #2
    1. Advertising

  3. Edward Rutherford

    Eric Sosman Guest

    On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    > If I have an union
    >
    > union U {
    > struct X x;
    > struct Y y;
    > struct Z z;
    >
    > } u;
    >
    > and both struct Y and struct Z have a struct X as the first field, then
    > can I always access u.x.<field> even if I am actually putting a struct Y
    > or Z in u?


    Yes, for any practical implementation. But according to the
    letter of the law (as I read it), no.

    There is a special dispensation (6.5.2.3p5) for unions of
    structs that share a "common initial sequence" of elements. If
    `struct X' were `short shrift; double trouble; char broiled;' and
    `struct Y' were `short shrift; double trouble; long john_silver;',
    then you could access the `shrift' and `trouble' members of either,
    no matter which had been most recently stored in the union.

    *But* your union isn't like that. Your `struct Y' actually looks
    like `struct X marks_the_spot; long john_silver;', and so does not
    share a "common initial sequence" with `struct X'. X's first element
    is a `short', Y's is a `struct X', `short' and `struct X' are not
    compatible types, so there's no "common initial sequence."

    You could regain compatibility by "expanding" the `struct X'
    in `struct Y', listing its elements explicitly rather than lumping
    them together as a `struct X' instance. That is, if `struct Y' were
    `short snort; double down; long john_silver;' all would be well.

    ... as it almost certainly will be anyhow, on any practical
    implementation. The objection I raise is an incredibly nit-picky,
    angels-on-pinheads kind of argument that no practical programmer
    would pay attention to -- until the optimizer bit his behind. And
    it's possible I'm misinterpreting "corresponding members." This
    may be a question for the kilobuck-an-hour language lawyers.

    --
    Eric Sosman
    d
     
    Eric Sosman, May 28, 2011
    #3
  4. Edward Rutherford

    Joe Pfeiffer Guest

    Eric Sosman <> writes:

    > On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    >> If I have an union
    >>
    >> union U {
    >> struct X x;
    >> struct Y y;
    >> struct Z z;
    >>
    >> } u;
    >>
    >> and both struct Y and struct Z have a struct X as the first field, then
    >> can I always access u.x.<field> even if I am actually putting a struct Y
    >> or Z in u?

    >
    > Yes, for any practical implementation. But according to the
    > letter of the law (as I read it), no.
    >
    > There is a special dispensation (6.5.2.3p5) for unions of
    > structs that share a "common initial sequence" of elements. If
    > `struct X' were `short shrift; double trouble; char broiled;' and
    > `struct Y' were `short shrift; double trouble; long john_silver;',
    > then you could access the `shrift' and `trouble' members of either,
    > no matter which had been most recently stored in the union.
    >
    > *But* your union isn't like that. Your `struct Y' actually looks
    > like `struct X marks_the_spot; long john_silver;', and so does not
    > share a "common initial sequence" with `struct X'. X's first element
    > is a `short', Y's is a `struct X', `short' and `struct X' are not
    > compatible types, so there's no "common initial sequence."
    >
    > You could regain compatibility by "expanding" the `struct X'
    > in `struct Y', listing its elements explicitly rather than lumping
    > them together as a `struct X' instance. That is, if `struct Y' were
    > `short snort; double down; long john_silver;' all would be well.
    >
    > ... as it almost certainly will be anyhow, on any practical
    > implementation. The objection I raise is an incredibly nit-picky,
    > angels-on-pinheads kind of argument that no practical programmer
    > would pay attention to -- until the optimizer bit his behind. And
    > it's possible I'm misinterpreting "corresponding members." This
    > may be a question for the kilobuck-an-hour language lawyers.


    This is totally irrelevant to the actual content of your post, but I'm
    in awe of your examples. Casually stringing together a series of puns
    like that to really good purpose is just amazing.
    --
    "Erwin, do you know what happened to the cat?" -- Mrs. Shroedinger
     
    Joe Pfeiffer, May 28, 2011
    #4
  5. Joe Pfeiffer wrote:
    > Eric Sosman <> writes:
    >
    > > On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    > >> If I have an union


    ..OT
    Is this (english) usage common? It rings funny in my middle-american
    ears.
    The long "u" begins with a 'yi' sound that serves as a consonant.
    ..\OT

    > >>
    > >> union U {
    > >> struct X x;
    > >> struct Y y;
    > >> struct Z z;
    > >>
    > >> } u;
    > >>
    > >> and both struct Y and struct Z have a struct X as the first field, then
    > >> can I always access u.x.<field> even if I am actually putting a struct Y
    > >> or Z in u?

    > >
    > > Yes, for any practical implementation. But according to the
    > > letter of the law (as I read it), no.
    > >
    > > There is a special dispensation (6.5.2.3p5) for unions of
    > > structs that share a "common initial sequence" of elements.


    Shouldn't it work on the level of 'elementary' elements?
    Ie. down to the raw types.

    > > If
    > > `struct X' were `short shrift; double trouble; char broiled;' and
    > > `struct Y' were `short shrift; double trouble; long john_silver;',
    > > then you could access the `shrift' and `trouble' members of either,
    > > no matter which had been most recently stored in the union.
    > >
    > > *But* your union isn't like that. Your `struct Y' actually looks
    > > like `struct X marks_the_spot; long john_silver;', and so does not
    > > share a "common initial sequence" with `struct X'. X's first element
    > > is a `short', Y's is a `struct X', `short' and `struct X' are not
    > > compatible types, so there's no "common initial sequence."
    > >
    > > You could regain compatibility by "expanding" the `struct X'
    > > in `struct Y', listing its elements explicitly rather than lumping
    > > them together as a `struct X' instance. That is, if `struct Y' were
    > > `short snort; double down; long john_silver;' all would be well.
    > >
    > > ... as it almost certainly will be anyhow, on any practical
    > > implementation. The objection I raise is an incredibly nit-picky,
    > > angels-on-pinheads kind of argument that no practical programmer
    > > would pay attention to -- until the optimizer bit his behind. And
    > > it's possible I'm misinterpreting "corresponding members." This
    > > may be a question for the kilobuck-an-hour language lawyers.

    >
    > This is totally irrelevant to the actual content of your post, but I'm
    > in awe of your examples. Casually stringing together a series of puns
    > like that to really good purpose is just amazing.


    Ditto. Pedogogical gold.

    luser-d

    > --
    > "Erwin, do you know what happened to the cat?" -- Mrs. Shroedinger


    "It cannot be known; but I can find out!"
     
    luser- -droog, May 28, 2011
    #5
  6. Edward Rutherford

    Ian Collins Guest

    On 05/28/11 08:03 PM, luser- -droog wrote:
    > Joe Pfeiffer wrote:
    >> Eric Sosman<> writes:
    >>
    >>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    >>>> If I have an union

    >
    > ..OT
    > Is this (english) usage common? It rings funny in my middle-american
    > ears.
    > The long "u" begins with a 'yi' sound that serves as a consonant.


    No, words starting with a u that is sounded like a y (as in you) are
    exceptions to the an before a vowel rule.

    > ..\OT


    --
    Ian Collins
     
    Ian Collins, May 28, 2011
    #6
  7. Edward Rutherford

    Willem Guest

    Ian Collins wrote:
    ) On 05/28/11 08:03 PM, luser- -droog wrote:
    )> Joe Pfeiffer wrote:
    )>> Eric Sosman<> writes:
    )>>
    )>>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    )>>>> If I have an union
    )>
    )> ..OT
    )> Is this (english) usage common? It rings funny in my middle-american
    )> ears.
    )> The long "u" begins with a 'yi' sound that serves as a consonant.
    )
    ) No, words starting with a u that is sounded like a y (as in you) are
    ) exceptions to the an before a vowel rule.

    However, "an union" is perfectly correct if you're referring
    to the multi-layered vegetable.


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, May 28, 2011
    #7
  8. Edward Rutherford

    Eric Sosman Guest

    On 5/28/2011 4:03 AM, luser- -droog wrote:
    > Joe Pfeiffer wrote:
    >> Eric Sosman<> writes:
    >>
    >>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    >>>> If I have an union

    >
    > .OT
    > Is this (english) usage common? It rings funny in my middle-american
    > ears.
    > The long "u" begins with a 'yi' sound that serves as a consonant.
    > .\OT
    >
    >>>>
    >>>> union U {
    >>>> struct X x;
    >>>> struct Y y;
    >>>> struct Z z;
    >>>>
    >>>> } u;
    >>>>
    >>>> and both struct Y and struct Z have a struct X as the first field, then
    >>>> can I always access u.x.<field> even if I am actually putting a struct Y
    >>>> or Z in u?
    >>>
    >>> Yes, for any practical implementation. But according to the
    >>> letter of the law (as I read it), no.
    >>>
    >>> There is a special dispensation (6.5.2.3p5) for unions of
    >>> structs that share a "common initial sequence" of elements.

    >
    > Shouldn't it work on the level of 'elementary' elements?
    > Ie. down to the raw types.


    Padding could be a problem. Let's take a concrete example:

    struct X {
    double trouble;
    char broiled;
    };

    struct Y {
    double trouble;
    char broiled;
    short snort;
    };

    struct Z {
    struct X marks_the_spot;
    short snort;
    };

    union Pacific{ // just so 6.5.2.3p5 applies
    struct X x;
    struct Y y;
    struct Z z;
    };

    On many machines, you are likely to find that sizeof(struct Z)
    is greater than sizeof(struct Y), and offsetof(struct Z, snort)
    is unequal to offsetof(struct Y, snort). So even though struct Y
    and struct Z begin with the same sequence of elementary members,
    they nonetheless do not share a "common initial sequence" and do
    not have the same layout.

    --
    Eric Sosman
    d
     
    Eric Sosman, May 28, 2011
    #8
  9. Edward Rutherford

    Joe Pfeiffer Guest

    Willem <> writes:

    > Ian Collins wrote:
    > ) On 05/28/11 08:03 PM, luser- -droog wrote:
    > )> Joe Pfeiffer wrote:
    > )>> Eric Sosman<> writes:
    > )>>
    > )>>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    > )>>>> If I have an union
    > )>
    > )> ..OT
    > )> Is this (english) usage common? It rings funny in my middle-american
    > )> ears.
    > )> The long "u" begins with a 'yi' sound that serves as a consonant.
    > )
    > ) No, words starting with a u that is sounded like a y (as in you) are
    > ) exceptions to the an before a vowel rule.
    >
    > However, "an union" is perfectly correct if you're referring
    > to the multi-layered vegetable.


    The mis-spelled multi-layered vegetable, at any rate.
    --
    "Erwin, do you know what happened to the cat?" -- Mrs. Shroedinger
     
    Joe Pfeiffer, May 28, 2011
    #9
  10. On May 28, 8:49 am, Eric Sosman <> wrote:
    > On 5/28/2011 4:03 AM, luser- -droog wrote:
    >
    >
    >
    > > Joe Pfeiffer wrote:
    > >> Eric Sosman<>  writes:

    >
    > >>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    > >>>> If I have an union

    >
    > > .OT
    > > Is this (english) usage common? It rings funny in my middle-american
    > > ears.
    > > The long "u" begins with a 'yi' sound that serves as a consonant.
    > > .\OT

    >
    > >>>> union U {
    > >>>>       struct X x;
    > >>>>       struct Y y;
    > >>>>       struct Z z;

    >
    > >>>> } u;

    >
    > >>>> and both struct Y and struct Z have a struct X as the first field, then
    > >>>> can I always access u.x.<field>   even if I am actually putting a struct Y
    > >>>> or Z in u?

    >
    > >>>      Yes, for any practical implementation.  But according tothe
    > >>> letter of the law (as I read it), no.

    >
    > >>>      There is a special dispensation (6.5.2.3p5) for unions of
    > >>> structs that share a "common initial sequence" of elements.

    >
    > > Shouldn't it work on the level of 'elementary' elements?
    > > Ie. down to the raw types.

    >
    >      Padding could be a problem.  Let's take a concrete example:
    >
    >         struct X {
    >             double trouble;
    >             char broiled;
    >         };
    >
    >         struct Y {
    >             double trouble;
    >             char broiled;
    >             short snort;
    >         };
    >
    >         struct Z {
    >             struct X marks_the_spot;
    >             short snort;
    >         };
    >
    >         union Pacific{  // just so 6.5.2.3p5 applies
    >             struct X x;
    >             struct Y y;
    >             struct Z z;
    >         };
    >
    > On many machines, you are likely to find that sizeof(struct Z)
    > is greater than sizeof(struct Y), and offsetof(struct Z, snort)
    > is unequal to offsetof(struct Y, snort).  So even though struct Y
    > and struct Z begin with the same sequence of elementary members,
    > they nonetheless do not share a "common initial sequence" and do
    > not have the same layout.


    Understood, but trouble and broiled should be ok, right? ie.
    accessible
    through all the union members having assigned through any one of them.
     
    luser- -droog, May 29, 2011
    #10
  11. Edward Rutherford

    Eric Sosman Guest

    On 5/29/2011 3:41 AM, luser- -droog wrote:
    > On May 28, 8:49 am, Eric Sosman<> wrote:
    >> On 5/28/2011 4:03 AM, luser- -droog wrote:
    >>
    >>
    >>
    >>> Joe Pfeiffer wrote:
    >>>> Eric Sosman<> writes:

    >>
    >>>>> On 5/27/2011 4:58 PM, Edward Rutherford wrote:
    >>>>>> If I have an union

    >>
    >>> .OT
    >>> Is this (english) usage common? It rings funny in my middle-american
    >>> ears.
    >>> The long "u" begins with a 'yi' sound that serves as a consonant.
    >>> .\OT

    >>
    >>>>>> union U {
    >>>>>> struct X x;
    >>>>>> struct Y y;
    >>>>>> struct Z z;

    >>
    >>>>>> } u;

    >>
    >>>>>> and both struct Y and struct Z have a struct X as the first field, then
    >>>>>> can I always access u.x.<field> even if I am actually putting a struct Y
    >>>>>> or Z in u?

    >>
    >>>>> Yes, for any practical implementation. But according to the
    >>>>> letter of the law (as I read it), no.

    >>
    >>>>> There is a special dispensation (6.5.2.3p5) for unions of
    >>>>> structs that share a "common initial sequence" of elements.

    >>
    >>> Shouldn't it work on the level of 'elementary' elements?
    >>> Ie. down to the raw types.

    >>
    >> Padding could be a problem. Let's take a concrete example:
    >>
    >> struct X {
    >> double trouble;
    >> char broiled;
    >> };
    >>
    >> struct Y {
    >> double trouble;
    >> char broiled;
    >> short snort;
    >> };
    >>
    >> struct Z {
    >> struct X marks_the_spot;
    >> short snort;
    >> };
    >>
    >> union Pacific{ // just so 6.5.2.3p5 applies
    >> struct X x;
    >> struct Y y;
    >> struct Z z;
    >> };
    >>
    >> On many machines, you are likely to find that sizeof(struct Z)
    >> is greater than sizeof(struct Y), and offsetof(struct Z, snort)
    >> is unequal to offsetof(struct Y, snort). So even though struct Y
    >> and struct Z begin with the same sequence of elementary members,
    >> they nonetheless do not share a "common initial sequence" and do
    >> not have the same layout.

    >
    > Understood, but trouble and broiled should be ok, right? ie.
    > accessible
    > through all the union members having assigned through any one of them.


    I think they'll be all right on any practical implementation,
    but I don't believe the Standard actually says so. In particular,
    the Standard does not guarantee things will work if you simply
    boil things down to "the level of 'elementary' elements," ignoring
    their membership in larger aggregations; that's what my example
    was intended to show.

    --
    Eric Sosman
    d
     
    Eric Sosman, May 29, 2011
    #11
  12. Edward Rutherford

    Tim Rentsch Guest

    Edward Rutherford <> writes:

    > If I have an union
    >
    > union U {
    > struct X x;
    > struct Y y;
    > struct Z z;
    >
    > } u;
    >
    > and both struct Y and struct Z have a struct X as the first field, then
    > can I always access u.x.<field> even if I am actually putting a struct Y
    > or Z in u?


    If you do this

    u.y = some_y; /* or u.z = some_z; */

    then an access to u.x.<field> has to work.
     
    Tim Rentsch, May 31, 2011
    #12
  13. Edward Rutherford

    Eric Sosman Guest

    On 5/31/2011 4:32 AM, Tim Rentsch wrote:
    > Edward Rutherford<> writes:
    >
    >> If I have an union
    >>
    >> union U {
    >> struct X x;
    >> struct Y y;
    >> struct Z z;
    >>
    >> } u;
    >>
    >> and both struct Y and struct Z have a struct X as the first field, then
    >> can I always access u.x.<field> even if I am actually putting a struct Y
    >> or Z in u?

    >
    > If you do this
    >
    > u.y = some_y; /* or u.z = some_z; */
    >
    > then an access to u.x.<field> has to work.


    Chapter and verse? (If "6.5.2.3p5," please explain why it applies.)

    --
    Eric Sosman
    d
     
    Eric Sosman, May 31, 2011
    #13
  14. Edward Rutherford

    Tim Rentsch Guest

    Eric Sosman <> writes:

    > On 5/31/2011 4:32 AM, Tim Rentsch wrote:
    >> Edward Rutherford<> writes:
    >>
    >>> If I have an union
    >>>
    >>> union U {
    >>> struct X x;
    >>> struct Y y;
    >>> struct Z z;
    >>>
    >>> } u;
    >>>
    >>> and both struct Y and struct Z have a struct X as the first field, then
    >>> can I always access u.x.<field> even if I am actually putting a struct Y
    >>> or Z in u?

    >>
    >> If you do this
    >>
    >> u.y = some_y; /* or u.z = some_z; */
    >>
    >> then an access to u.x.<field> has to work.

    >
    > Chapter and verse? (If "6.5.2.3p5," please explain why it applies.)


    Consider this case:

    union {
    char *pc;
    void *pv;
    } u;

    u.pv = some_character_pointer;
    ... now access u.pc ...

    If we believe the footnote for 6.5.2.3p3 (it's footnote 82 in
    N1256) then the access to u.pv has to work. (The two pointer
    types here have the same size and representation, so there
    are no representational issues or implementation-defined
    behavior dependencies on that account.)

    Similarly,

    struct Y {
    void *pv;
    };

    union {
    char *pc;
    struct Y y;
    } u;

    u.y = some_y;
    ... now access u.pc ...

    has to work, because storing into u.y stores into exactly
    the same bits as the u.pv case above, and (by the footnote)
    these bits must be reinterpreted when accessing u.pc.

    Now we have this case:

    struct X { ... };

    struct Y {
    struct X x;
    ...
    };

    union {
    struct X x;
    struct Y y;
    } u;

    u.y = some_y;
    ... now access u.x.<field> ...

    The assignment into u.y stores into the member u.y.x, and
    any field in u.y.x exactly lines up with the corresponding
    field in u.x. So, again by the footnote, the access u.x.<field>
    must load the very same field that was stored by assigning to
    u.y.

    I accept the premise that the footnote accurately reflects
    what the Standard normatively requires here; it's hard to
    imagine anyone seriouly reaching a different conclusion,
    except perhaps to argue that some other part of the Standard
    is therefore wrong and so should be re-worded.
     
    Tim Rentsch, Jun 1, 2011
    #14
    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:
    669
    Matt Garman
    Apr 25, 2004
  2. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    876
    Chris Torek
    Apr 26, 2004
  3. nicolas.sitbon

    union field access and compatible types

    nicolas.sitbon, Jan 8, 2010, in forum: C Programming
    Replies:
    6
    Views:
    514
    Tim Rentsch
    Jan 13, 2010
  4. Sound
    Replies:
    2
    Views:
    454
    Randy Webb
    Sep 28, 2006
  5. jr
    Replies:
    3
    Views:
    426
Loading...

Share This Page