e244
e244

Reputation: 71

static_cast void* char* vs static_cast void** char**

If I do the following all is ok:

char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok

But the following is not:

char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
                               //cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
                               //cannot convert from 'void **' to 'char **'

Please can someone explain to me why the second examples are not allowed. Please don't quote the C++ standard as your whole answer, because I've already seen answers that quote it, and I don't understand what they meant. I want to understand why the second examples don't work (ie. if you could give an example where it would be dangerous that would be a great help). Because I don't get it. To me, both examples are casting pointers. Why does an additional level of indirection make any difference?

Upvotes: 7

Views: 2151

Answers (2)

The restriction is to avoid breaking the type system. The first conversion is fine:

type *p = ...;
void *vp = p;

While you are giving away the type, you cannot inflict too much damage to the original value without since there is little to be done with a void object and all changes to vp are local to the pointer and cannot affect p.

If the second case was allowed:

type **p = ...;
void **vp = p;

Then perfectly looking and correct code could break your application. For example:

int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double();  // now parray[0] is a pointer to a double object, 
                     // not a pointer to an int!!!

The type system has been subverted.

That is, the problem is that in the second case there are operations that can be applied to the destination pointer that can modify the original object and cause bugs. Similar examples can be found with const other cases (you can convert int* to const int*, but you cannot convert int** to const int**...).

Upvotes: 6

Mats Petersson
Mats Petersson

Reputation: 129374

A void * pointer can point at "anything", and it is valid to convert all pointers to a void *, and it is valid to convert all pointers from void * to some other type.

However, a void ** is a pointer that points to a void * value. And a char ** is a pointer that points to char * value. These types don't point to the types that are convertible from one another. You can, if you NEED to do this, use void **vpp = reinterpret_cast<void **>(cpp);, but it's "not safe" (you are basically telling the compiler "Look, I know what I'm doing here, so just do it", which may not do what you actually expected...)

Upvotes: 12

Related Questions