Reputation: 8036
Can someone explain this to me:
char* a;
unsigned char* b;
b = a;
// error: invalid conversion from ‘char*’ to ‘unsigned char*’
b = static_cast<unsigned char*>(a);
// error: invalid static_cast from type ‘char*’ to type ‘unsigned char*’
b = static_cast<unsigned char*>(static_cast<void*>(a));
// everything is fine
What makes the difference between cast 2 and 3? And are there any pitfalls if the approach from 3 is used for other (more complex) types?
[edit] As some mentioned bad design, etc...
This simple example comes from an image library which gives me the pointer to the image data as char*
. Clearly image intensities are always positive so I need to interpret it as unsigned char
data.
Upvotes: 4
Views: 7227
Reputation: 69672
static_cast<void*>
annihilate the purpose of type checking as you say that now it points on "something you don't know the type of". Then the compiler have to trust you and when you say static_cast<unsigned char*>
on your new void*
then he'll just try to do his job as you ask explicitely.
You'd better use reinterpret_cast<>
if you really must use a cast here (as it's obvioulsy showing a design problem here).
Upvotes: 7
Reputation: 39896
beware, when you cast to void* you lose any type information.
what you are trying to do is incorrect, and false, and error prone and misleading. that's why the compilator returned a compilation error :-)
a simple example
char* pChar = NULL; // you should always initalize your variable when you declare them
unsigned char* pUnsignedChar = NULL; // you should always initalize your variable when you declare them
char aChar = -128;
pChar = &aChar;
pUnsignedChar = static_cast<unsigned char*>(static_cast<void*>(pChar));
then, though pUnsignedChar == pChar
nonethless we have *pUnsignedChar == 255
and *pChar == -128
.
i do believe this is bad joke, thus bad code.
Upvotes: 0
Reputation: 28087
Your third approach works because C++ allows a void pointer to be casted to T*
via static_cast
(and back again) but is more restrictive with other pointer types for safety reasons. char
and unsigned char
are two distinct types. This calls for a reinterpret_cast
.
Upvotes: 5
Reputation: 223999
Casts between pointers require reinterpret_cast
, with the exception of void*
:
Casts from any pointer to to void*
are implicit, so you don't need to explicitly cast:
char* pch;
void* p = pch;
Casts from void*
to any other pointer only require a static_cast
:
unsigned char* pi = static_cast<unsigned char*>(p);
Upvotes: 1
Reputation: 1116
static_cast between pointers works correct only if one of pointers is void or that's casting between objects of classes, where one class is inherited by another.
Upvotes: 2
Reputation: 146900
The difference between 2 and 3 is that in 3, you're explicitly telling the compiler to stop checking you by casting to void*. If the approach from 3 is used for, pretty much anything that isn't a direct primitive integral type, you will invoke undefined behaviour. You may well invoke undefined behaviour in #3 anyway. If it doesn't cast implicitly, it's almost certainly a bad idea unless you really know what's going on, and if you cast a void* back to something that wasn't it's original type, you will get undefined behaviour.
Upvotes: 1
Reputation: 29001
C++ tries to be a little bit more restrictive to type casting than C, so it doesn't let you convert chars to unsigned chars using static_cast
(note that you will lose sign information). However, the type void*
is special, as C++ cannot make any assumption for it, and has to rely on the compiler telling it the exact type (hence the third cast works).
As for your second question, of course there are a lot of pitfals on using void*
. Usually, you don't have to use it, as the C++ type system, templates, etc. is rich enough to not to have to rely in that "unknown type". Also, if you really need to use it, you have to be very careful with casts to and from void*
controlling that types inserted and obtained are really the same (for example, not pointer to subclasses, etc.)
Upvotes: 2