1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
The third new-style cast is used to change the em(interpretation) of
information: the tt(reinterpret_cast). It is somewhat reminiscent of the
tt(static_cast), but tt(reinterpret_cast) should only be used when it is
em(known) that the information as defined in fact is or can be interpreted as
something completely different. Its syntax is:
verb( reinterpret_cast<pointer type>(pointer expression))
Think of the tt(reinterpret_cast) as a cast offering a poor-man's union:
the same memory location may be interpreted in completely different ways.
The tt(reinterpret_cast) is used, for example, in combination with the
tt(write) function that is available for em(streams). In bf(C++) streams are
the preferred interface to, e.g., disk-files. The standard streams like
tt(std::cin) and tt(std::cout) also are stream objects.
Streams intended for writing (`output streams' like tt(cout)) offer tt(write)
members having the prototype
verb( write(char const *buffer, int length))
To write the value stored within a tt(double) variable to a stream in its
un-interpreted binary form the stream's tt(write) member is used. However, as
a tt(double *) and a tt(char *) point to variables using different and
unrelated representations, a tt(static_cast) cannot be used. In this case a
tt(reinterpret_cast) is required. To write the raw bytes of a variable
tt(double value) to tt(cout) we use:
verb( cout.write(reinterpret_cast<char const *>(&value), sizeof(double));)
All casts are potentially dangerous, but the tt(reinterpret_cast) is the
most dangerous of them all. Effectively we tell the compiler: back off, we
know what we're doing, so stop fuzzing. All bets are off, and we'd better
em(do) know what we're doing in situations like these. As a case in point
consider the following code:
verb( int value = 0x12345678; // assume a 32-bits int
cout << "Value's first byte has value: " << hex <<
static_cast<int>(
*reinterpret_cast<unsigned char *>(&value)
);)
The above code produces different results on little and big endian
computers. Little endian computers show the value 78, big endian
computers the value 12. Also note that the different representations used by
little and big endian computers renders the previous example
(tt(cout.write(...))) non-portable over computers of different architectures.
As a i(rule of thumb): if circumstances arise in which casts em(have) to be
used, clearly document the reasons for their use in your code, making double
sure that the cast does not eventually cause a program to misbehave. Also:
avoid tt(reinterpret_casts) unless you em(have) to use them.
|