Topic: Defect report: interpretation of an (old-style) cast to unsigned char *
Author: Gennaro Prota <gennaro_prota@yahoo.com>
Date: Tue, 20 Jan 2004 19:57:02 +0000 (UTC) Raw View
[Note: Forwarded to C++ Commitee -sdc ]
Please, note this is not the same as core issue 242.
The following code:
int main()
{
int i = 1;
*(unsigned char*) (&i) = 0;
}
is, according to 5.4 [expr.cast], not portable in C++ because the cast
to unsigned char* has the same behavior as a reinterpret_cast
(notoriously not portable). However the same code is perfectly legal
and portable in C. In fact, both C90 and C99 guarantee that an lvalue
of type unsigned char can be used to read and write the object
representation of any object (subject to other restrictions, of
course; e.g. not writing to a non-modifiable object, using a suitable
volatile qualification, etc.; anyhow, under the appropriate conditions
one can, this way, even access an uninitialized object).
I don't claim to give a resolution, but these are a few thoughts that
could be considered for discussion. I think it's obvious that the
old-style cast should be made portable in C++ too, at least when the
source type is a POD. The problem is "how" to make it so and to what
extent:
a) is the guarantee (that any object can be accessed as an array of
unsigned chars) to be extended to non-POD types? And to
base-subobjects?
b) should an old style cast be the only way to do the conversion above
or do we want a new-style way as well? In the second case, a look at
the list in [expr.cast] par. 5 shows that, cv-qualifiers apart, the
choice is between static_cast and reinterpret_cast.
Both choices have advantages. As to static_cast note that this is
already, AFAIK, portable:
static_cast<unsigned char*> ( static_cast<void*> (&i) );
So we already have a two-pass static_cast that "works".
One reason to prefer static_cast would be that static_cast is
generally for portable conversion (as we want this one to be) while
one reason to prefer reinterpret_cast is that it would then be easy
and natural to allow a portable reinterpret_cast<unsigned char&> too.
The problem of references to unsigned char of course doesn't arise
from C compatibility but can be important for consistency (why,
otherwise, could I cast the address of x to unsigned char* but not x
to unsigned char&?). An explicit wording of the standard making such a
cast portable would also be important for techniques like
template <typename T> T* addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
used in boost::addressof (Supposing that I use unsigned char instead
of char, does the above become portable?)
Genny.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]