Pregunta

Entiendo que reinterpret_cast Es peligroso, sólo estoy haciendo esto para probarlo.Tengo el siguiente código:

int x = 0;
double y = reinterpret_cast<double>(x);

Cuando intento compilar el programa me da un error que dice

conversión no válida del tipo 'flotante' al tipo 'doble

¿Qué está sucediendo?Pensé reinterpret_cast era el elenco rebelde que podías usar para convertir manzanas en submarinos, ¿por qué no se compila este elenco simple?

¿Fue útil?

Solución

Mediante la asignación y al valor devuelto por el elenco en realidad no estás echando la x valor, que está convirtiendo la misma. Es decir, no y sí apunta a x y pretender que apunte a un flotador. Conversión construye un nuevo valor de tipo float y le asigna el valor de x. Hay varias maneras de hacer esta conversión en C ++, entre ellos:

int main()
{
    int x = 42;
    float f = static_cast<float>(x);
    float f2 = (float)x;
    float f3 = float(x);
    float f4 = x;
    return 0;
}

La única diferencia real es la última (una conversión implícita) generará un compilador de diagnóstico en los niveles más altos de advertencia. Pero todos lo hacen funcionalmente lo mismo - y en muchos casos realmente lo mismo, al igual que en el mismo código de máquina

.

Ahora bien, si usted realmente quiere pretender que x es un flotador, entonces realmente quieres lanzar x, al hacer esto:

#include <iostream>
using namespace std;

int main()
{
    int x = 42;
    float* pf = reinterpret_cast<float*>(&x);
    (*pf)++;
    cout << *pf;
    return 0;
}

Se puede ver lo peligroso que es. De hecho, la salida cuando ejecuta este en mi máquina es 1, que decididamente no es 42 + 1.

Otros consejos

En C++ reinterpret_cast solo puede realizar un conjunto específico de conversiones, enumeradas explícitamente en la especificación del idioma.En breve, reinterpret_cast solo puede realizar conversiones de puntero a puntero y conversiones de referencia a referencia (más conversiones de puntero a entero y de entero a puntero).Esto es consistente con la intención expresada en el propio nombre del elenco:está destinado a ser utilizado para la reinterpretación de punteros/referencias.

Lo que estás intentando hacer no es una reinterpretación.Si quieres reinterpretar un int como un double Tendrías que convertirlo a un tipo de referencia.

double y = reinterpret_cast<double&>(x); 

aunque la reinterpretación equivalente basada en punteros es probablemente más explícita

double y = *reinterpret_cast<double*>(&x); // same as above

Tenga en cuenta, sin embargo, que mientras reinterpret_cast puede convertir los tipos de referencia/puntero, el intento real de leer los datos a través de la referencia/puntero resultante produce un comportamiento indefinido.

Y en cualquier caso esto, por supuesto, no puede tener mucho sentido en una plataforma con int y double de diferente tamaño (ya que en caso de mayor double Leerás más allá de la memoria ocupada por x).

Entonces, al final, todo se reduce a lo que intentabas lograr.¿Reinterpretación de la memoria?Véase más arriba.Algún tipo de más significativo int a double ¿conversión?En ese caso, reinterpret_cast No te ayudará aquí.

reinterpret_cast no es un reparto general. De acuerdo con la sección de especificaciones C ++ 03 5.2.10.1:

  

Conversiones que se pueden realizar de forma explícita el uso de reinterpret_cast se enumeran a continuación. Ningún otro cambio se realiza de manera explícita usando reinterpret_cast.

Y no aparece nada que describe la conversión entre tipos de puntos integrales y flotantes (o entre tipos enteros, incluso esto es reinterpret_cast<long>(int(3)); ilegal)

Si está intentando convertir los bits de su int a una representación de un double, es necesario emitir el Dirección no el valor. También debe asegurarse de que los tamaños coinciden:

uint64_t x = 0x4045000000000000;
double y = *reinterpret_cast<double *>(&x);

El compilador rechaza lo que escribió como una tontería porque int y double pueden ser objetos de diferentes tamaños. Se podría conseguir el mismo efecto de esta manera, aunque es ciertamente peligroso:

int x = 0;
double y = *reinterpret_cast<double*>(&x);

Esto es potencialmente peligroso ya que si x y y son diversos tamaños (digamos int es de cuatro bytes y double es de ocho bytes), entonces cuando eliminar la referencia de los ocho bytes de memoria en &x rellenar y se accede a cuatro bytes de x y cuatro bytes de ... lo que venga después en la memoria (posiblemente el inicio de y, o basura, o algo completamente distinto.)

Si desea convertir un número entero a un doble, use un static_cast y se llevará a cabo la conversión.

Si desea acceder al patrón de bits de x, fundido a algún tipo de puntero conveniente (por ejemplo, byte*) y el acceso hasta sizeof(int) / sizeof(byte):

byte* p = reinterpret_cast<byte*>(&x);
for (size_t i = 0; i < sizeof(int); i++) {
  // do something with p[i]
}

reinterpretar fundido le permite reinterpretar un bloque de memoria como un tipo diferente. Esto tiene que ser realizada sobre los punteros o referencias

int x = 1;
float & f = reinterpret_cast<float&>(x);
assert( static_cast<float>(x) != f );   // !!

La otra cosa es que es de hecho un reparto bastante peligroso, no sólo debido a los valores extraños que salen como los resultados, o la aserción anterior no fallan, sino porque si los tipos son de diferentes tamaños, y se reinterpretan desde ' fuente' a '' tipos de destino, cualquier operación en la referencia / puntero reinterpretados accederá bytes sizeof(destination). Si sizeof(destination)>sizeof(source) entonces que va a ir más allá de la memoria de variables reales, lo que podría matar a su aplicación o overwritting otras variables distintas de la fuente o destino:

struct test {
   int x;
   int y;
};
test t = { 10, 20 };
double & d = reinterpret_cast<double&>( t.x );
d = 1.0/3.0;
assert( t.x != 10 ); // most probably at least.
asswet( t.y != 20 );

reinterpret_cast es la mejor opción para los punteros. Por lo que un puntero a un objeto se puede convertir en un "submarino".

MSDN :

  

El operador reinterpret_cast puede ser   utilizado para las conversiones tales como char * a   int * o * a One_class   Unrelated_class *, que son inherentemente   inseguro.

     

El resultado de una reinterpret_cast   No puede con seguridad ser utilizado para cualquier cosa   aparte de ser echado de nuevo a su   tipo original. Otros usos son, por lo   mejor, no portátil.

El enfoque reinterpretar me llevó por un camino extraño, con resultados inconstantes. Al final me encontré mucho mejor a memcpy así!

double source = 0.0;
uint64_t dest;
memcpy(&dest, &source, sizeof(dest));

casting un int a un doble no requiere un yeso. El compilador de realizar los trabajos de manera implícita.

El reinterpret_cast se utiliza con punteros y referencias, por ejemplo, que emitan un int * a un double *.

Eso es interesante. A lo mejor es hacer una conversión implícita de int a flotar antes de intentar el elenco de duplicar. int y flotan tipos tienden a ser del mismo tamaño en bytes (dependiendo de su sistema, por supuesto).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top