Re: Unions Redux



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
.



Relevant Pages

  • Re: Unions Redux
    ... union {int s; unsigned int us;} u; ... -- The value of a union member other than the last one stored ... A valid object representation of a signed integer ...
    (comp.lang.c)
  • Re: Behavior of the code
    ... Dan Henry wrote: ... representations: c0 and c0 hold bits ... conversion to the returned value. ... unsigned int) the return expression would yield the unsigned *value* ...
    (comp.lang.c)
  • Re: Integer Promotion?
    ... represented by an int, ... What if a signed short had 56 value bits and no padding bits, and a signed int had 48 value bits and 8 padding bits? ... But IMHO programmers do themselves ... in floating-point representations; they are usually content to let ...
    (comp.lang.c)
  • Re: Bit Padding and other questions
    ... So if an int has padding bits, ... Not quite -- that's two different object representations for the same ... family functions read is returned casted to (unsigned char)? ...
    (comp.lang.c)
  • Re: Aliasing rules - int and long
    ... required to have pure binary representations. ... But there's no guarantee that the value bits in unsigned int ... point discussing standard C semantics. ...
    (comp.lang.c)