Как использовать reinterpret_cast в С++?
Я знаю, что reinterpret_cast в С++ можно использовать следующим образом:
float a = 0;
int b = *reinterpret_cast<int*>(&a);
Но почему его нельзя использовать напрямую?
float a = 0;
int b = reinterpret_cast<int>(a);
error: invalid cast from type 'float' to type 'int'
Ответы
Ответ 1
Вы не можете reinterpret_cast в том случае, если вы даете, потому что reinterpret_cast принимает только либо int, чтобы преобразовать в указатель, либо наоборот, и следует за дополнительными аналогичными правилами.
Здесь есть сводка этих правил: http://en.cppreference.com/w/cpp/language/reinterpret_cast
Ответ 2
Все reinterpret_cast
позволяет вам читать переданную вами память по-другому. Вы даете ему место памяти, и вы просите его прочитать эту память, как будто это то, о чем вы ее просили. Вот почему его можно использовать только с указателями и ссылками.
Возьмем этот код в качестве примера:
#include <iostream>
int main()
{
float a = 12;
int b = *reinterpret_cast<int*>(&a);
std::cout << b;
}
Итак, чтобы разбить эту строку кода на более подробные сведения *reinterpret_cast<int*>(&a);
:
- Возьмите адрес
a
-
reinterpret_cast
до int*
- Верните
int*
, который указывает на a
- Отмечать значение возвращаемого указателя как
int
Теперь, когда я запускаю это, я получаю 1094713344
, причина в том, что это 12 как float
с использованием IEEE, представлена как 0100 0001 0100 0000 0000 0000 0000 0000
в двоичном формате. Теперь возьмите этот двоичный код и прочитайте его как unsigned int
, затем вы получите 1094713344
.
Вот почему reinterpret_cast
считается очень опасным и почему его не следует использовать в подобных случаях.
Вы должны использовать его только в том случае, если указатель указывает на память, и вам нужно прочитать эту память определенным образом, и вы знаете, что память может быть прочитана таким образом.
Ответ 3
почему он не может использовать его напрямую?
Я считаю, что это чистое дизайнерское решение, чтобы сделать С++ более безопасным по типу, чем C.
reinterpret_cast
очень опасен, поскольку он может включать тип сглаживания, что является коротким способом для undefined поведения. Когда вы используете С++ casts, вы подписываете контракт с вашим компилятором "Я знаю, что я делаю". Итак, все эти длинные имена операторов, угловые скобки, преобразования типа-указателя типа говорят вам: "Подождите, не делайте этого. Возможно, что-то не так в вашем коде!".
Кроме того, не все компиляторы С++ допускают наложение типов (либо путем литья, либо с помощью соединений).
Ответ 4
С помощью reinterpret_cast
вы можете использовать тип указателя для любого другого типа указателя, например
вы можете использовать указатель float
для указателя int
:
float *a = new int(0);
int* b = reinterpret_cast<int*>(a);
Ответ 5
Во втором случае это не отличное от значения a
до b
. На самом деле это просто конверсия. b
не будет указывать на x
и делать вид, что он указывает на поплавок. Conversion создает новое значение типа int и присваивает ему значение от a
.
В С++ есть несколько способов сделать это преобразование.
Один из них - просто использовать статический приведение, как обычно. Это рекомендуемое решение:
int b = static_cast<int>(a);
Вы можете использовать reinterpret_cast следующим образом. Обратите внимание, что это делает переинтерпретацию для бит-биттера, а не преобразование в отличие от упомянутых альтернатив:
int b = reinterpret_cast<int&>(a);
Вы также можете использовать стиль C:
int b = (int)a;
Вы также можете использовать кастинг функций функции С++:
int b = int(a);
Вы также можете получить неявный разговор, хотя это может вызвать предупреждение:
int b = a;
Статический приведение рекомендуется в этом специальном случае, но, по крайней мере, не используйте неявный разговор, а также стиль C в С++.