简体   繁体   English

为什么不能static_cast一个双void指针?

[英]Why can't static_cast a double void pointer?

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 . 我知道将void指针static_cast为任何其他指针类型的正确方法是使用static_cast However, you can't static_cast a double void pointer to another double pointer of other type. 但是,你不能static_cast一个double void指针指向另一个类型的另一个双指针。

Q: 问:

  1. Why we can't static_cast a double void pointer? 为什么我们不能static_cast一个双void指针?
  2. What's the proper way to cast a double void pointer? 什么是投射双void指针的正确方法?

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. 当你有一个void*并将它转换为int* ,可能会或可能没有一些数学/宽度调整来创建一个正确类型的实例, static_cast<>将准备这样做。 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; 当你只有一个指向void*的指针并想要一个指向int*的指针时, static_cast<>对指向的void*对象没有写访问权; 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* . 它是不是可以自由调整它以确保它是一个有效的int*这样static_cast<>可以成功并返回一个真正可用于访问有效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.) (请记住,期望static_cast<>为使用static_cast<int*>(the_void_ptr)初始化的int*安排一些额外的内存是static_cast<int*>(the_void_ptr) - 不仅会产生意外的开销,而且还会需要在线程特定的内存中或动态分配并以某种方式释放,并且实际最终比较指针值的所有代码方式都会中断。)

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. 如果你想强迫这件事并向编译器保证两种类型的宽度相同并且不需要进行数学调整等等 - 那么你可以使用reinterpret_cast<>并对其进行调整,明确表示你接受了风险未定义的行为。

void* is special in that it can point to anything. void*的特殊之处在于它可以指向任何东西。 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. 因此,对于某些类型T ,转换为void*T*是“正常”操作, static_cast可以支持该操作。 In effect, such a conversion says: "The pointer doesn't know to what it points, but I know it: it points to a T ." 实际上,这样的转换说:“指针不知道它指向的是什么,但我知道它:它指向T

void** is not special special in this way. void**这种方式并不特殊。 It can point to one thing only, to a void* . 它只能指向一个事物,一个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." void**转换为int**表示不同的东西:“指针声称它指向void* ,但我想将其视为指向int*的指针。” And if you want to treat one thing as a different thing, you want to reinterpret the original - so use reinterpret_cast . 如果你想把一件事当作另一件事,你想要重新解释原件 - 所以使用reinterpret_cast

I believe this is an XY-problem. 我相信这是一个XY问题。 Depending on the circumstances it can be solved without reinterpret_cast . 根据具体情况,可以在没有reinterpret_cast的情况下解决。 If you know that the void** pointer in fact points to a pointer to int , you can safely do this: 如果您知道void**指针实际上指向指向int的指针,则可以安全地执行此操作:

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

Unless you really need int** in your code. 除非你真的需要在你的代码中使用int** 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. 但要注意它会指向一个局部变量iptr ,它会在超出范围时被销毁。

There are good answers for Q1, and the answer to Q2 depends a lot on the intention. Q1的答案很好,Q2的答案在很大程度上取决于意图。 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: 如果void **v_dptr旨在成为指向“泛型” void*的指针,您知道它实际上是一个int*并且您想要相应地进行转换,以下可能是您想要的:

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

A static_cast can do the reverse of any implicit conversion. static_cast可以执行任何隐式转换的反向操作。

There is an implicit conversion int*void* ; 有一个隐式转换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** . 没有隐式转换int**void** If it was allowed it would reinterpret the object pointer to, namely, reinterpreting an int* as a void* . 如果允许,它会重新解释对象指针,即将int*重新解释为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). 在一些旧体系结构中, int*不一定具有与void* (或char* ,具有最小对齐要求的指针类型)一样大的值表示。

The reinterpretation requires a reinterpret_cast . 重新解释需要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. 恕我直言,这是用一个好主意reinterpret_cast 一般从转换到/ void* ,因为意图传达给读者。 However, as I recall Sutter and Alexandrescu recommended using static_cast , presumably due to a lack of a formal guarantee in C++03. 但是,我记得Sutter和Alexandrescu推荐使用static_cast ,可能是因为C ++ 03缺乏正式的保证。 Also as I recall, that purely formal problem was fixed in C++11. 我还记得,在C ++ 11中修复了纯正式的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM