Согласно http://en.cppreference.com/w/cpp/language/reinterpret_cast, известно, что reinterpret_cast
указатель на интеграл достаточного размера и обратно дает то же значение. Мне интересно, верно ли соответствие стандартам. То есть reinterpret_cast
интеграл с типом указателя достаточного размера и обратно дает то же значение?Переводит ли reinterpret_casting интеграл в тип указателя и обратно, дает то же значение?
ответ
Нет, это не гарантируется стандартом. Цитирование все части C++ 14 (n4140) [expr.reinterpret.cast], которые относятся указатель – целочисленные преобразования, курсив мой:
4 Указатель может быть явно преобразован в любой интегральный тип достаточно большой, чтобы держать его , Функция отображения - . [Примечание: Предполагается, что неудивительно тем, кто знает структуру адресации лежащей в основе машины. -end note] ...
5 Значение интегрального типа или типа перечисления может быть явно преобразовано в указатель. Указатель преобразован в целое число достаточного размера (если таковое существует в реализации) и обратно к тому же типу указателя будет иметь свое первоначальное значение; сопоставления между указателями и целыми числами определяются иначе. [Примечание: За исключением случаев, описанных в п. 3.7.4.3, результат такого преобразования не будет отображаемым значением . -end примечание]
Так, начиная с интегральным значением и преобразование его в указатель и обратно (не предполагая никаких проблем размера) определяется реализацией. Это означает, что вы должны проконсультироваться с документацией вашего компилятора, чтобы узнать, сохраняет ли такой маршрут в оба конца или нет. Таким образом, он, конечно, не переносится.
Я получаю именно эту проблему в библиотеке, экспортирующей указатели на объекты как непрозрачные идентификаторы, и теперь попытка восстановить эти указатели от внешних вызовов не работает для старых процессоров x86 (во время Windows 98). Итак, хотя мы можем ожидать такого поведения, в общем случае это неверно. В 386-CPU адрес состоит из наложенных указателей, поэтому адрес любой позиции памяти не является уникальным, и я обнаружил, что возврат обратно не восстанавливает исходное значение.
Нет, это не гарантируется. Например, различные целые числа могут преобразовываться в один и тот же адрес. –
@ н.м. Не могли бы вы привести конкретный пример? Обратите внимание, что здесь используется 'reinterpret_cast' для выполнения преобразования. – Lingxi
Возьмите архитектуру 8086. Целое число 0x10002000L при интерпретации 0x1000: 0x2000 (сегмент и смещение) соответствует физическому адресу 0x12000. Точно так же целое число 0x12000000L. Ничто не мешает компилятору преобразовывать 0x10002000L в сегмент 0x1200: 0x0000 и смещение, а затем преобразовать его обратно в 0x12000000L. В плохие старые времена это было известно как нормальная нормализация указателя. –