Reputation: 3118
I was just reading this thread: Simple c++ pointer casting
And that got me to thinking why a static_cast between different pointer types is not allowed (except in the cases in which it is) unless you static_cast to a void* as an intermediary step. It seems to me that either both or neither should be allowed. Here is an example:
char* cs;
unsigned char* ucs;
cs = reinterpret_cast<char*>(ucs); // 1) allowed, of course
cs = static_cast<char*>(ucs); // 2) not allowed: incompatible pointer types
cs = static_cast<char*>( static_cast<void*>(ucs) ); // 3) now it's allowed!
It seems to me that if #3 is possible then #2 should be allowed as well. Or conversely, if #2 is not allowed on the grounds that the pointers are not compatible (necessitating a reinterpret_cast) then perhaps static_casting from a void* to anything should not be allowed on the grounds of pointer incompatibility. (Casting to a void* from any other pointer is always okay, of course.)
So why isn't one of those possilities true - that #2 and #3 are either both allowed or neither allowed? Why does it instead work as shown in my example?
Upvotes: 9
Views: 7621
Reputation: 3118
Okay, I'm going to take a stab at answering my own question here because I think I'm getting an idea, although I'm not sure it's right. You can let me know if you think I'm getting it by up/down voting my answer, I guess. :)
So I think static_cast
is telling the compiler, "Trust me, this is safe." Whereas reinterpret_cast
is telling the compiler, "I know this is unsafe; do it anyway."
So going back to my examples:
cs = reinterpret_cast<char*>(ucs);
is unsafe, but the compiler will do it anyway because you told it to.
cs = static_cast<char*>(ucs);
will result in a compiler error because you said, "Trust me, this is safe," but the compiler knows that it really is not. So it doesn't trust you because it actually knows in this case, and therefore errors.
Now the last example has two parts:
void* temp = static_cast<void*>(ucs);
is allowed of course because casting to void* is safe.
cs = static_case<char*>(temp); // remember temp is a void*
is allowed because casting from a void* is sometimes safe and sometimes not - the compiler cannot tell which it is in any given instance... so when you say, "Trust me, this is safe," the compiler trusts you - and if you're wrong, then that's on your head. O.O
So in other words, you cannot static_cast
something that is never a safe case - that's when you need reinterpret_cast
... but you can static_cast
something that is sometime safe and sometimes not (and the compiler can't tell which is the case in any given instance).
All that said... I refered to "safe" and "unsafe" casts a lot here, but what do those words actually mean? (And so, to some extent, I still don't even understand my own answer here...! Please comment if you can help me figure that out...)
Upvotes: 1
Reputation: 76498
The problem is this:
my_type *p = new my_type;
void *vp = p; // okay
Now if you need to get the original pointer back you do this:
my_type *new_p = static_cast<my_type*>(vp); // okay
That's fine, and the result is well defined. You get undefined behavior if you use static_cast
to convert the pointer to a different type than the original pointer, and that's not something the compiler can, in general, detect. So the cast is allowed, and if you misuse it, it's on your head.
Upvotes: 1
Reputation: 208456
cs = static_cast<char*>( static_cast<void*>(ucs) ); // 3) now it's allowed!
It will compile. Does it mean that it is allowed? Not. The standard allows conversions from void*
to T*
only in the case where the void*
was obtained by a conversion from T*
, which is not your case.
Upvotes: 4