union field access

E

Edward Rutherford

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?
 
S

Shao Miller

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);
 
E

Eric Sosman

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

Joe Pfeiffer

Eric Sosman said:
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.
 
L

luser- -droog

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

Shouldn't it work on the level of 'elementary' elements?
Ie. down to the raw types.
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

"It cannot be known; but I can find out!"
 
I

Ian Collins

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

Willem

Ian Collins wrote:
) On 05/28/11 08:03 PM, luser- -droog wrote:
)> Joe Pfeiffer wrote:
)>>
)>>> 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
 
E

Eric Sosman

.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


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

Joe Pfeiffer

Willem said:
Ian Collins wrote:
) On 05/28/11 08:03 PM, luser- -droog wrote:
)> Joe Pfeiffer wrote:
)>>
)>>> 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.
 
L

luser- -droog

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

Eric Sosman

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

Tim Rentsch

Edward Rutherford said:
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.
 
E

Eric Sosman

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

Tim Rentsch

Eric Sosman said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top