Подтвердить что ты не робот

Как использовать 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'
4b9b3361

Ответ 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 в С++.