Когда reinterpret_cast изменяет биты?
Из стандарта С++:
5.2.10.3
Отображение, выполняемое reinterpret_cast, может или не может быть выполнено представление, отличное от исходного значения.
Меня обучили на этом сайте, чтобы поверить и повторить это. (Даже если это возможно просто мелочи). A reinterpret_cast
от float*
до int*
разрешено создавать другой битовый шаблон. Единственная гарантия заключается в том, что reinterpret_cast
-издание, возвращаемое к float*
, приведет к созданию исходного битового рисунка.
Мой вопрос: Это когда-нибудь случается? Существует ли существующая реальная платформа или процессор или компилятор, который на самом деле reinterpret_cast
для другого битового шаблона? Если нет, существуют ли ситуации реального мира, где reinterpret_cast
имеет какие-либо служебные данные во время выполнения?
Во всем моем опыте с reinterpret_cast
, приведение было директивой для компилятора, а не для среды выполнения.
Ответы
Ответ 1
Я работал на платформах, где char*
больше, чем int*
,
и на платформах, где у них был другой макет, хотя
размер был тот же. Ни одна из рассматриваемых машин не является
особенно актуальным сегодня (хотя, во-вторых,
PDP-10, был одним из наиболее важных машин в период расцвета).
Также возможно, что некоторые режимы компиляции на Intel в
родной режим (или то, что раньше назывался нативным режимом)
"нормализовать" указатели в reinterpret_cast
, или даже
неявное преобразование, чтобы облегчить сравнение адресов.
Также возможно (хотя я этого не видел), что такое
преобразования обеспечивают правильное выравнивание, например. конверсия из
char*
до int*
может привести к тому, что 2 младших бита будут равны 0. В
практика, однако, сегодня я не думаю, что вы, вероятно,
см. a reinterpret_cast
внести любые изменения между указателем данных
типы. Вопрос более исторический. (Но я не уверен в
современные встроенные процессоры. Насколько я понимаю, многие из них
являются адресацией слов, и поэтому, если sizeof(int) != sizeof(char)
, они
вероятно, потребуется специальный формат для адресации char
.)
Ответ 2
Указатели могут в принципе быть разных размеров. Самый большой указатель, если есть какая-либо разница (без учета указателей элементов, говорящих о реальных указателях), char*
, так как a char
по определению является байтом и может быть где угодно, без выравнивания. void*
должен иметь возможность представлять char*
.
В системе с int*
, использующей меньшее количество бит, чем char*
, повторное интерпретирование в этом направлении может быть немного рискованным.
Я думаю, что с этими указателями (хе) вы можете найти это в стандарте. Требование о void*
достаточно велико для любого указателя, а также о выравнивании: более строгая/большая, чем меньше бит, необходимых для указателя на этот тип. Но я никогда не слышал о какой-либо существующей системе, где есть такая разница.
Стандартные относительно void*
могут представлять char*
:
С++ 11 §3.9.2/4:
"
Можно использовать указатель на cv-квалификацию (3.9.3) или cv-unqualified void
указывать на объекты неизвестного типа. Такой указатель должен иметь возможность удерживать любой объект указатель. Объект типа cv void*
должен иметь одинаковый представления и выравнивания, как cv char*
"Любой указатель объекта" подразумевает смутно, что существуют разные размеры указателя.
Standareese относительно выравнивания референта:
С++ 11 §5.2.10/7:
"
Указатель объекта может быть явно преобразован в указатель объекта другого типа. Когда prvalue v
типа" указатель на T1
"преобразуется в тип" указатель на cv T2
", результат is static_cast<
cv T2*>(static_cast<
cv void*>(v))
, если оба T1
и T2
> являются стандартными типами макетов (3.9) и выравниванием требования T2
не более строгие, чем теги T1
, или если любой тип void
. Преобразование prvalue типа" указатель на T1
"на тип" указатель на T2
" (где T1
и T2
- это типы объектов и где выравнивание требования T2
не более строгие, чем требования T1
) и обратно к исходному типу дают исходный указатель стоимость. Результат любого другого такого преобразования указателя не указан.
Стоит отметить, что позже в стандарте есть некоторая поддержка эмуляции класса класса деривации класса, которая, по-видимому, противоречит "любому другому" в конце выше:
С++ 11 §9.2/20,
"
Указатель на объект структуры стандартного макета, соответствующим образом преобразованный с помощью reinterpret_cast
, указывает на его начальный член (или если этот элемент является битовым полем, а затем блоку, в котором он находится) и наоборот.
В этом случае оба объекта обязательно имеют одно и то же выравнивание, в то время как предыдущий цитированный параграф говорил только о выравнивании типов – но явно формальное небольшое противоречие не является практической проблемой, как я ее вижу.