It might be helpful to consider two different use cases for static_cast
: one for converting non-pointer types to one another, and one for converting pointer types to one another.
When converting non-pointer types to one another, static_cast
has the meaning of "do the kind of conversion that you would do if you initialized an object of the target type from the source value." So, for example, in this code:
int aASCII = 64;
cout << static_cast<char>(aASCII) << endl; // Prints 'A'
the static_cast<char>(aASCII)
means "give me the char
value I would get here if I were to initialize a new char
value to aASCII
." It's analogous to doing the following:
int aASCII = 64;
char temp = aASCII;
cout << temp << endl;
Similarly, consider this code:
int total = 137;
int numItems = 42;
cout << static_cast<double>(total) / numItems << endl;
the static_cast<double>(total)
bit means "pretend that total
is a double
here when doing the division." It's analogous to writing
int total = 137;
int numItems = 42;
double temp = total;
cout << temp / numItems << endl;
With that in mind, why doesn't this code compile?
double yy = static_cast<double>(u); // Oops!
The reason why is that this is kinda sorta is like writing
double temp = u; // Oops, doesn't compile
double yy = temp;
Here, this won't compile because you can't initialize a double
to a variable of union
type U
.
The use of static_cast
with pointers uses a different set of rules. When working with pointers, static_cast
means "please pretend the pointer points at an object of the type I want it to point at, but only if there's some plausible universe in which that could work." So, for example, this is perfectly legal:
Base* ptr = new Derived;
Derived* dPtr = static_cast<Derived*>(ptr);
Here, this says "I have a pointer of type Base*
. There is a plausible world in which it really points to a Derived
. Please convert the pointer to a Derived*
, but don't do any runtime checks to make sure this is safe. I'm aware that if this doesn't actually point at a Derived
, then Bad Things will happen."
You couldn't, however, write this:
float* ptr = new float[137];
Derived* dPtr = static_cast<Derived*>(ptr); // Error!
This won't work because there's no way for a pointer of type float*
to point at a Derived
object (without doing something really horrible to some pointer at some point in time).
The reason that your code
double* y = static_cast<double*>(x); // y's value is "pointer to u.b"
is fine is because x
is a void*
, which can point at any (non-function) entity, so it's plausible that it could point at a double
.