Re: Signed/Unsigned Conversion
On 4/27/07 6:48 AM, in article
4631d840$0$30352$9a6e19ea@news.newshosting.com, "Ron Natalie"
<ron@spamcop.net> wrote:
Greg Herlihy wrote:
well there is a theoretical difficulty in that it relies on undefined
behaviour. C++ (and C) only guarantee reading data via the member by
which it was written. There is an exception in that it is always allowed
to read data as unsigned char.
No, the code is completely defined. Since x_.u and x.i have the same size
and address - and since the declared type of each is either the signed or
unsigned version of the same integral type (in this case, an int), then the
rules of C++ expressly allow a program to retrieve from both - a value that
was stored in either. Specifically, a program may store an unsigned value in
x_.u and then retrieve it from x.u as an unsigned value (as well as the
other other way around):
Sorry, Francis was right and you are wrong. There is no such rule as
you state. The only defined behavior with reading memory using a
different type from which is used to store it is when you are using
(possibly unsigned) chars.
Not so. There are in fact eight ways (including the two that you know
about) in which a C++ program may safely access the stored value of an
object through an lvalue. After all, C++ would not be able to support
such essential language features like class inheritance or polymorphic
types if it were the case the every stored value had to be accessed
with the same type that was used to store it - or as a char.
So for educational purposes, here is the complete list:
"If a program attempts to access the stored value of an object through
an lvalue of other than one of the following types the behavior is
undefined:
- the dynamic type of the object,
- a cv-qualified version of the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to the
dynamic type of the object,
- a type that is the signed or unsigned type corresponding to a cv-
qualified version of the dynamic type of the object,
- an aggregate or union type that includes one of the aforementioned
types among its members (including, recursively, a member of a
subaggregate or contained union),
- a type that is a (possibly cv-qualified) base class type of the
dynamic type of the object,
- a char or unsigned char type. [?3.10/15]
The third bullet point (which is the one I cited in my previous post)
covers the original example. The program in that case was using a
union of a signed int and unsigned int to "alias" a single, stored
value. And as the above language from the Standard makes clear - a
program that accessing a stored, signed value as a value of the
corresponding unsigned type (or the other way around) - does not have
undefined behavior.
In fact, the only nonexistent rule that has been brought up thus far
is the one mentioned in Francis's post: that accessing the value of an
inactive union member has undefined behavior. The truth is that no
such rule exists anywhere in the Standard. So the only possible
explanation why accessing an inactive union member would have
undefined behavior - would be precisely because the type of the value
stored and the type of the lvalue used to access it - was not
expressly covered by any of the eight bullet points in the (not so)
nonexistent list above.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]