Да, если ... (или "Да, но ...") и нет в противном случае.
Стандарт определяет (3.7.4.3) следующее:
- Значение указателя является безопасно полученным указателем [...], если оно является результатом четко определенного преобразования указателя или
reinterpret_cast
из безопасно полученного значения указателя [или] результатом reinterpret_cast
целочисленного представления безопасно полученного значения указателя
- Целочисленное значение - это целочисленное представление безопасно полученного указателя [...], если его тип по крайней мере равен
std::intptr_t
и [...] результат reinterpret_cast
безопасного производное значение указателя [или]
результат действительного преобразования целочисленного представления значения указателя, полученного безопасным способом [или] результат аддитивной или побитовой операции, один из операндов которой является целочисленным представлением
безопасное значение указателя
- Объект отслеживаемого указателя - это [...] объект целочисленного типа, который по крайней мере равен
std::intptr_t
Стандарт далее гласит, что реализации могут быть упрощенными или могут быть строгими в отношении принудительного применения производных от указателей безопасных значений. Это означает, что не определено, вызывает ли использование или разыменование небезопасно полученного указателя неопределенное поведение (это забавно!)
Что в целом означает не больше и не меньше, чем "что-то другое может работать в любом случае, но единственная безопасная вещь, как указано выше".
Следовательно, , если вы либо используете std::intptr_t
в первую очередь (предпочтительнее!), Либо если вы знаете, что размер хранилища любого целочисленного типа вы используете (скажем, long
) ), по крайней мере, размером std::intptr_t
, тогда допустимо и четко определено (то есть «безопасно») привести к вашему целочисленному типу и обратно. Стандарт гарантирует, что.
Если это не так, преобразование из указателя в целочисленное представление, вероятно, (или, по крайней мере, возможно) потеряет некоторую информацию, и обратное преобразование не даст действительного указателя. Или может случайно, но это не гарантируется.
Интересный анекдот состоит в том, что стандарт C ++ не напрямую не определяет std::intptr_t
вообще; он просто говорит "то же, что 7.18 в стандарте C" .
Стандарт C, с другой стороны, утверждает, что "обозначает целочисленный тип со знаком со свойством, которое любое допустимое
указатель на void может быть преобразован в этот тип, затем преобразован обратно в указатель на void, и результат будет равен исходному указателю ".
Это означает, что без довольно сложных определений, приведенных выше (в частности, последнего бита первой маркированной точки), было бы невозможно преобразовать в / из чего угодно, кроме void*
.