Всегда допустимо преобразовывать указатель на тип в указатель на другой тип , включая void , поэтому, если T является типом, это допустимо C ++:
T* x;
void *y = reinterpret_cast<void *>(x);
В реальном мире оно никогда не используется, потому что void *
- это особый случай, и вы получаете то же значение с помощью static_cast
:
void *y = static_cast<void *>(x); // equivalent to previous reinterpret_cast
(на самом деле приведенное выше преобразование является неявным и может быть просто записано void *y = x;
- спасибо Майклу Кензелу за то, что он заметил)
Чтобы быть более точным, стандарт даже говорит в черновике n4659 для C ++ 17 8.2.10 Reinterpret cast [expr.reinterpret.cast], §7
Когда значение v из
тип указателя объекта преобразуется в тип указателя объекта «указатель на cv T», в результате получается static_cast<cv T*>(static_cast<cv void*>(v))
.
Когда вы ссылаетесь на то, что byte и char являются единственными допустимыми типами, это просто то, что разыменование разрешено преобразовывать указатель только для этих типов. void
сюда не входит, потому что вы никогда не можете разыменовать void *
.
Чтобы конкретно ответить на ваш вопрос
.. Я кастую из int ** в пустоту *. И я в конечном итоге приведу из пустоты * обратно к int **.
Стандарт гарантирует, что первым является стандарт (неявное чтение):
Значение типа «указатель на cv T», где T - тип объекта, может быть преобразовано в значение типа «указатель»
резюме ". Значение указателя (6.9.2) не изменяется при этом преобразовании.
Так что это всегда законно:
int **i = ...;
void *v = i;
Для обратного литья стандартно сказано (в параграфе static_cast
):
Значение типа «указатель на cv1 void» можно преобразовать в значение типа «указатель на cv2 T»,
Так что это тоже законно
int **j = static_cast<int **>(v);
и стандарт гарантирует, что j == i
.