Приведение числовых типов через reinterpret_cast

245
08 марта 2017, 20:19

Если мы используем reinterpret_cast для приведения указателя к указателю, объекта к указателю или указателя к объекту, то приведение осуществляется корректно.

int n = 0;
char* c = reinterpret_cast<char*>(n);
int another_value = reinterpret_cast<int>(c);

Почему reinterpret_cast не позволяет осуществлять приведение на простых форматах? Такой код не собирается:

int a = 0;
char b = reinterpret_cast<char>(a);

по Страуструпу:

reinterpret_cast управляет преобразованиями между несвязанными типами, например целых в указатели или указателей в другие(несвязанные) указатели.

по Майерсу:

reinterpret_cast предназначен для низкоуровневых приведений, которые порождают зависимые от реализации (то есть непереносимые) результаты, например приведение указателя к int.

Итак, и указатель к указателю, и указатель к int, и int к указателю посредством reinterpret_cast приводятся.

Алена Л. в блоге пишет:

reinterpret_cast - самое нахальное приведение типов. Не портируемо, результат может быть некорректным, никаких проверок не делается. Считается, что вы лучше компилятора знаете как на самом деле обстоят дела, а он тихо подчиняется. Не может быть приведено одно значение к другому значению. Обычно используется, чтобы привести указатель к указателю, указатель к целому, целое к указателю. Умеет также работать со ссылками.

Хорошо, одно значение к другому не может быть приведено. Почему эту возможность не запилили?

Answer 1

reinterpret_cast, как видно из названия, предназначен в первую очередь для выполнения переинтерпретации памяти. То есть когда вы приводите указатель типа T * к указателю типа U *, то предполагается, что вы это делаете для того, чтобы обратиться к памяти исходного объекта типа T, как к памяти объекта типа U. В этом и заключается переинтерпретации памяти. (Разумеется, легальность такого доступа зависит еще от массы посторонних факторов.)

reinterpret_cast также поддерживает аналог такого указательного преобразования, но в варианте со ссылками вместо указателей, т.е. вы можете сделать

T t;
U &u = reinterpret_cast<U &>(t);

и далее получать доступ к памяти объекта t как объекта типа U.

Также на reinterpret_cast дополнительно "повесили" побочную функциональность - приведение между указательными и целыми типами. Все.

А вот чего вы хотели добиться, выполняя reinterpret_cast типа int к типу char - не ясно. Если вам нужна именно переинтерпретация памяти, то это делается так

int a = 0;
char b = reinterpret_cast<char &>(a);

то есть целевой тип должен быть ссылкой.

Ваш же вариант выглядит как обычное преобразование типов, выполняемое static_cast, а не reinterpret_cast. Вся идея разнообразия типов кастов в С++ как раз и сводится к разделению обязанностей между ними с минимальными пересечениями.

Answer 2

Смотрите.

Преобразования бывают двух типов: меняющие внутреннее представление, и не меняющие его.

Преобразование int в double меняет внутреннее представление, double имеет хитрый бинарный layout с мантиссой и порядком. Преобразование целочисленных типов тоже меняет внутреннее представление, если у них разные длины.

А вот смысл reinterpret_cast, наоборот, в том, что он меняет тип объекта с точки зрения компилятора, и (кроме возможных патологических компиляторов) никак не отображается в объектном коде. Вы ж помните, что объект — это просто набор бит в памяти и его тип, позволяющий интерпретировать его? reinterpret_cast просто просит компилятор интерпретировать его по-другому, не меняя сами биты в памяти.

А преобразование, которое умеет делать всё, преобразовывать и числовые типы, и указатели, уже запилили. Это C-style cast. Правда, из-за избыточной мощи его использование не рекомендуется — именно потому, что он может и числа преобразовать, и указатели, и вашего кота, даже если вы этого и не хотели.

READ ALSO
Другая компоновка в классе-потомке

Другая компоновка в классе-потомке

ЗдравствуйтеЕсть класс ComparisionTable, наследуемый от QWidget с виджетами: два QLabel и один QTableWidget

223
Парсинг JSON в Javascript из Python

Парсинг JSON в Javascript из Python

Передаю данные с сервераПолучаю дату на клиенте

334
Форма добавления вкладок в HTML+js [требует правки]

Форма добавления вкладок в HTML+js [требует правки]

Подскажите, как сделать такое меню добавления вкладок из списка, пожалуйста

235