Re: Unions Redux
- From: pa@xxxxxxxxxxxxxxxxxxxxx (Pierre Asselin)
- Date: Thu, 15 Mar 2007 02:32:29 +0000 (UTC)
Old Wolf <oldwolf@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, but it still makes sense to
look at section 6.2.6.1 to see why the behavior is unspecified.
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).
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.
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.
--
pa at panix dot com
.
- Follow-Ups:
- Re: Unions Redux
- From: Robert Gamble
- Re: Unions Redux
- References:
- Unions Redux
- From: Old Wolf
- Unions Redux
- Prev by Date: Re: Aliasing rules - int and long
- Next by Date: Re: Correct way to cast
- Previous by thread: Unions Redux
- Next by thread: Re: Unions Redux
- Index(es):
Relevant Pages
|