On 12/24/2015 11:59 PM, Paul wrote:
> I'm confused about when conversions between types are allowed.
> int* z = new int(3);
> char* x= (char*)z; //works fine.
Assuming that by "works fine" you mean "no compilation error", then that
doesn't say much, really. Lots of code will compile but will not "work
fine".
However, if you mean that the expression "*x" subsequently yields the
value 3, then that's an artifact of the machine architecture.
Namely, that in this case it stores integers with the least significant
at lowest address, which is called little endian (reportedly due to the
terminology used in Gulliver's Travels, written by Jonathan Swift, whose
poem about the recursiveness of things provided the main inspiration for
Augustus De Morgan's ditto poem about recursive fleas, which, as De
Morgan himself, is frequently mentioned in programming and computer
science books). If instead integers were stored in big endian format, or
worse, in some middle endian jumbled format, you'd get zero.
> However, if the second line is replaced by char* x = char*(z); I get
> "expected primary expression before char" compile error. I was
> anticipating that I can cast from int* to char* this way in the same
> way that you can cast 5.3 to int by writing int(5.3);
Casting pointers generally means you will be interpreting the bitpattern
in some new way.
This is generally known as type PUNNING, and in C++ it can be expressed
as a reinterpret_cast, e.g.
auto x = reinterpret_cast<char*>( z );
In contrast, when you convert 5.3 to int you're generating a new
bitpattern that to some degree, preferably via some precisely defined
formula or algorithm, preserves the original value. This is more
commonly referred to as a CONVERSION. In C++ it can be expressed as a
static_cast, e.g.
auto i = static_cast<int>( 5.3 );
In addition to static_cast and reinterpret_cast there's dynamic_cast,
const_cast and the case of using a C style cast to cast to inaccesible base.
This should ideally be discussed in your textbook?
> If the second line is replaced by char*x = z; I get an error -- "can
> not convert from char* to int* in initialization" How could I have
> know that such an initialization is illegal,
Initializing something of type X with something of type Y is only valid
if there is a single-step implicit conversion from Y to X.
This is a fundamental part of static type checking, which should also be
discussed in your text book?
> given that the cast of
> the form char* x = (char*)z; is ok ?
Oh, the term "OK" can mean so many things here, ranging from "no
compilation error" via "is one of the supported type punnings listed in
the whatever-it-was std's paragraph" to "does what I want".
But what you need to know up front right now is that a C style cast
generally just tells the compiler to "shut up! because I KNOW WHAT I'M
DOING". It also tells the compiler to do whatever is implied by the
current source code. Which can CHANGE when the source is maintained.
Obviously that's not a good idea when one doesn't know what one's doing.
So, preferably just avoid casts.
And when you absolutely need to use a cast, then choose one of the four
named C++ style casts mentioned above, or, if needed, a combination.
Cheers & hth.,
- Alf