tauran
tauran

Reputation: 8036

Simple c++ pointer casting

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

Answers (7)

Klaim
Klaim

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

Stephane Rolland
Stephane Rolland

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

sellibitze
sellibitze

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

sbi
sbi

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

zaynyatyi
zaynyatyi

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

Puppy
Puppy

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

Diego Sevilla
Diego Sevilla

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

Related Questions