Re: Unions Redux



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

.



Relevant Pages

  • Re: Unions Redux
    ... union {int s; unsigned int us;} u; ... depends on the object representation compatibility, ... all to do with the fact that there is a union involved. ... is a trap representation for signed int. ...
    (comp.lang.c)
  • Re: What is a type?
    ... The types are different but the underlying representation ... that an enumeration type exists at ... The type int is perfectly supported by ... When I get a 128MB memory disk in RAM/USB the sequence is linear ...
    (comp.lang.c)
  • Re: What is a type?
    ... The types are different but the underlying representation ... This makes it sound like an enumeration type and type "int" are ... Conversions between integer ...
    (comp.lang.c)
  • Re: Unions Redux
    ... in int to avoid problems with representation. ... if it were an unsigned int -- end of story. ... memcpy(chararray, &doubleval, sizeof intval); ... and clearly aliasing rules do not apply to the latter. ...
    (comp.lang.c)
  • Re: casting question - i64 = *((__int64*)&d);
    ... The safest and most portable way to transfer data between systems is to convert it to a textual representation -- but FP types may lose a tiny bit of accuracy during the conversion process. ... Any attempt at moving binary data requires a lot of attention to specifying the wire format and code to convert to/from that wire format on each machine, which has its own problems but is typically faster. ... Your double may be a trap representation when interpreted as an int. ...
    (comp.lang.c)