Re: Unions Redux
- From: "Robert Gamble" <rgamble99@xxxxxxxxx>
- Date: 14 Mar 2007 22:43:14 -0700
On Mar 14, 10:32 pm, p...@xxxxxxxxxxxxxxxxxxxxx (Pierre Asselin)
wrote:
Old Wolf <oldw...@xxxxxxxxxxxxxx> wrote:
[ snip ]
union { int s; unsigned int us; } u;
u.us = 50;
printf("%d\n", u.s);
I was looking at N1124. Annex J lists among the unspecified
behaviors,
-- The value of a union member other than the last one stored
into (6.2.6.1).
Annex J is informative, not normative,
Indeed it is not and in this case it is simply erroneous. The
sentence you cited is leftover from a previous version of the
Standard, there is no supporting text in the Standard proper.
but it still makes sense to
look at section 6.2.6.1 to see why the behavior is unspecified.
You are making the false assumption that 6.2.6.1 actually contains
verbiage to this effect, it doesn't.
There we see that u.s and u.us have object representations as
sequences of unsigned char (paragraphs 2,4), but that some object
representations may be trap representations leading to undefined
behavior when you access u.s (par. 5). Further down, 6.2.6.2(1-2)
leave open the possibility that int has more trap representations
than unsigned int, for example if there are padding bits or if ints
are sign-magnitude and M<N-1 in 6.2.6.2(2).
So it seems that your code has undefined (not just unspecified)
behavior, by 6.2.6.1(5).
I have no idea how you were able to come to that conclusion from
anything you have cited so far. You appear to have come to a
premature conclusion and then tried, unconvincingly, to make the
evidence fit that conclusion.
If you want to read your 50 as a signed int, you need to convert
the bits, e.g. by assignment, u.s= u.us; on a really wicked machine,
that assignment need not be a no-op !
My argument doesn't work the other way. 6.2.6.2(5) says:
A valid (non-trap) object representation of a signed integer
type where the sign bit is zero is a valid object representation
of the corresponding unsigned type, and shall represent
the same value.
The opposite is also true, 6.2.5p9:
"The range of nonnegative values of a signed integer type is a
subrange of the corresponding unsigned integer type, and the
representation of the same value in each type is the same."
so I haven't ruled out
u.s = 50;
printf("%u\n", u.us);
I can't see anything else in 6.2.6.1 that could rule it out, either.
Paragraph 6.2.6.1(7) applies, but I'm pretty sure that sizeof(int)==
sizeof(unsigned int) by 6.2.6.2 so there are no leftover bytes
for (7) to ... bite (D'oh).
Note that the aliasing rules in C99 6.5 are not violated here -- it is
not forbidden under that section to access an object of some type T
with an lvalue expression whose type is the signed or unsigned
version of T.
I don't think that's relevant. It says that the compiler must
assume, for optimization purposes, that u.s and u.us are potentially
aliased (well, duh). For example,
memcpy(buf, &u.us, sizeof(u.us)); /* unsigned char buf[BIG] */
do_something((const unsigned char *)buf);
u.s= 50;
memcpy(buf, &u.us, sizeof(u.us)); /* can't optimize out */
In other words, is there anything other than the aliasing rules that
restrict 'free' use of unions?
As I said, I don't think the aliasing rules matter. Your example
amounts to a C++ reinterpret_cast<int> and can hit a trap
representation.
I don't know what C++ has to do with this.
Robert Gamble
.
- Follow-Ups:
- Re: Unions Redux
- From: Pierre Asselin
- Re: Unions Redux
- References:
- Unions Redux
- From: Old Wolf
- Re: Unions Redux
- From: Pierre Asselin
- Unions Redux
- Prev by Date: regarding #define
- Next by Date: Re: Aliasing rules - int and long
- Previous by thread: Re: Unions Redux
- Next by thread: Re: Unions Redux
- Index(es):
Relevant Pages
|