Why can't static_cast a double void pointer?

好久不见. 提交于 2019-12-01 02:20:50

问题


Consider the following piece of code:

void **v_dptr(nullptr);
int  **i_dptr = static_cast<int**>(v_dptr);

The above example produces the following compile error:

static_cast from 'void **' to 'int **' is not allowed

LIVE DEMO

I know that the proper way to cast a void pointer to any other pointer type is to use static_cast. However, you can't static_cast a double void pointer to another double pointer of other type.

Q:

  1. Why we can't static_cast a double void pointer?
  2. What's the proper way to cast a double void pointer?

回答1:


When you have a void* and cast it to an int*, there may or may not be some mathematical/width adjustment to create an instance of the proper type, which static_cast<> will be prepared to do. When you have only a pointer to a void* and want a pointer to an int*, the static_cast<> has no write access to the pointed-to void* object; it is not free to adjust it to make sure it's a valid int* such that the static_cast<> can succeed and return a pointer which really can be used to access a valid int*. While on some architectures this may not matter, if the standard allowed this then the code could break when ported. (Keep in mind that it's unreasonable to expect the static_cast<> to arrange for some additional memory for an int* somewhere that it initialises using a static_cast<int*>(the_void_ptr) - not only would that have unexpected overheads, but it'd need to be in thread specific memory or allocated dynamically and released somehow, and all manner of code that actually ends up comparing the pointer values would break.)

If you want to force the matter and promise the compiler that the width of both types is the same and no mathematical adjustment is necessary etc. - then you can use reinterpret_cast<> and boss it around, making it clear you're accepting the risk of undefined behaviour.




回答2:


void* is special in that it can point to anything. It is a "pointer to unspecified type." Therefore, converting to and from void* to T* for some type T is a "normal" operation, one which static_cast can support. In effect, such a conversion says: "The pointer doesn't know to what it points, but I know it: it points to a T."

void** is not special special in this way. It can point to one thing only, to a void*. Converting a void** to an int** says something different: "The pointer claims it points to a void*, but I want to treat it as a pointer to int* instead." And if you want to treat one thing as a different thing, you want to reinterpret the original - so use reinterpret_cast.




回答3:


There are good answers for Q1, and the answer to Q2 depends a lot on the intention. If void **v_dptr is intended to be a pointer to a "generic" void* which you know is actually a int* and you want to cast accordingly, the following might be what you want:

int *i_ptr = static_cast<int*>(*v_dptr);
int **i_dptr = &i_ptr;



回答4:


I believe this is an XY-problem. Depending on the circumstances it can be solved without reinterpret_cast. If you know that the void** pointer in fact points to a pointer to int, you can safely do this:

int* iptr = static_cast<int*>(*v_dptr);

Unless you really need int** in your code. And if you need, you can do:

int** i_dptr = &iptr;

but beware that it will point to a local variable iptr which will be destroyed when goes out of scope.




回答5:


A static_cast can do the reverse of any implicit conversion.

There is an implicit conversion int*void*; it doesn't do more than lose the information about the type of the pointed to object.

There is no implicit conversion int**void**. If it was allowed it would reinterpret the object pointer to, namely, reinterpreting an int* as a void*. On some old architectures an int* did not necessarily have as large a value representation as a void* (or char*, the pointer types with the least alignment requirements).

The reinterpretation requires a reinterpret_cast.

IMHO it's a good idea to use reinterpret_cast in general for conversions to/from void*, because that communicates intent to the reader. However, as I recall Sutter and Alexandrescu recommended using static_cast, presumably due to a lack of a formal guarantee in C++03. Also as I recall, that purely formal problem was fixed in C++11.



来源:https://stackoverflow.com/questions/26277391/why-cant-static-cast-a-double-void-pointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!