--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
union
{
int number ;
char array[256] ;
} my_union ;
Someone is speaking well of you.
Well first off, using a union even in C to allow writing dat as one type
and reading it as another is undefined behaviour except in a small
number of special cases. Second using a reinterpret_cast will also
result in undefined behaviour most of the time. You need to know exactly
what you are doing and exactly which compiler you are using.
The simple answer is that unions were designed to safe space not as some
form of overlay facility. They are also often used in non-portable ways.
reinterpret_cast is essentially non-portable and should not be used
unless you understand exactly what you are doing on the hardware you are
using with the implementation of C++.
When you may use the same storage to store potentially different
objects and what that storage to have the appropriate alignment
requirements to be able to store said objects.
AFAIK reinterpret_cast is same as plain C pointer cast ( if it isn't,
it's damn close ;-) ), so question becomes why is there a union at
all?
One possible reason:
struct variant
{
enum type { int_, char_, char_pointer, float_ }
int type;
union
{
int i_data;
char c_data;
char* cp_data;
float f_data;
};
};
void f(const variant& v)
{
switch (v.type)
{
case variant::int_: return work_with(v.i_data);
case variant::char_: return work_with(v.c_data);
}
}
The above is arguably nicer than otherwise incessant casting on a data
member type.
Goran.
a bitfield structure union`ed with int is an excellent example where union
comes very handy. This is typically done in flags. iostream flags would be a
good example.
union is something that is safe, well-defined and conveys a design aspect.
I would use reinterpret_cast only if I am stuck with with code that I cannot
touch but badly need to use it in some other incompatible data format. If
the code is accessible I would always try to see if I can make changes to
avoid reinterpret_cast. By definition reinterpret_cast can give
different/unpredictable results on various platforms. We should be careful.
Although at one one place I find reinterpret_cast really handy, in embedded
system programming when I can typecast an integer to a pointer.
Regards,
Jyoti
For example (1) reinterpret_cast you use when you have to pass (or
receive) your data as raw bytes to (or from) some API that deals with
raw data (like cryptography or device level I/O). There will be always
such API's that do not care what it really is so you must reinterpret
the bytes yourself. You may achieve same effect with unions but you
may end up needing ridiculously numerous unions that way.
For example (2) union you use for (rare) performance critical tricks.
You may need fast polymorphic (variant) array without performance
overhead (from virtual functions and/or dynamically allocating each
element of array). As example (3) you may need union of float and
unsigned as hacking tool for fastly manipulating bits in that float.
You can achieve same effects with reinterpret_cast, but it makes your
performance-oriented tinkering even harder to read and understand.
Using union or reinterpret_cast for keeping different things
(variants) in same memory space is generally bad idea since union is
not object-oriented, its members may be only of plain old data types.
boost::variant is better suited for that purpose.
It depends on what you are trying to do. Unions are the
standard means of "overlaying" different data, in order to save
space. In C++, this doesn't always work as well as we'd like,
since most useful types can't be members of a union.
reinterpret_cast is designed to fill a completely different
need, that of type punning. In practice, reinterpret_cast
should only be used for very low level work.
--
James Kanze