static_cast reinterpret_cast español ejemplos dev cast c++ casting reinterpret-cast

c++ - español - ¿Por qué este reinterpret_cast no compila?



reinterpret_cast c++ ejemplos (9)

Entiendo que reinterpret_cast es peligroso, solo hago 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 diciendo

Conversión no válida del tipo ''float'' al tipo ''double

¿Que esta pasando? Pensé que reinterpret_cast era el elenco rogue que podías usar para convertir manzanas en submarinos, ¿por qué este simple yeso no se compila?


Al asignar y al valor devuelto por la conversión, realmente no está emitiendo el valor x , sino que lo está convirtiendo. Es decir, y no apunta a x y pretende que apunta a un flotador. La conversión construye un nuevo valor de tipo float y le asigna el valor de x . Hay varias formas de hacer esta conversión en C ++, entre ellas:

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 que la última (una conversión implícita) generará un diagnóstico del compilador en niveles de advertencia más altos. Pero todos hacen funcionalmente lo mismo, y en muchos casos lo mismo que en el mismo código de máquina.

Ahora, si realmente quieres pretender que x es un flotador, entonces realmente quieres lanzar x , haciendo esto:

#include <iostream> using namespace std; int main() { int x = 42; float* pf = reinterpret_cast<float*>(&x); (*pf)++; cout << *pf; return 0; }

Puedes ver lo peligroso que es esto. De hecho, la salida cuando ejecuto esto en mi máquina es 1 , que decididamente no es 42 + 1.


El compilador rechaza lo que escribiste como una tontería porque int y double pueden ser objetos con diferentes tamaños. Podrías lograr el mismo efecto de esta manera, aunque es ciertamente peligroso:

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

Esto es potencialmente peligroso porque si y son diferentes tamaños (digamos que int es de cuatro bytes y el double es de ocho bytes), entonces, cuando elimine la referencia de los ocho bytes de memoria en &x para completar y accederá a cuatro bytes de x y cuatro bytes. de ... lo que venga a continuación en la memoria (posiblemente el inicio de y , o la basura, o algo completamente distinto).

Si desea convertir un entero en un doble, use un static_cast y realizará la conversión.

Si desea acceder al patrón de bits de x , conviértalo a algún tipo de puntero conveniente (por ejemplo, byte* ) y acceda 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] }


En C ++, reinterpret_cast solo puede realizar un conjunto específico de conversiones, enumeradas explícitamente en la especificación del lenguaje. En resumen, 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 coherente con la intención expresada en el mismo nombre del modelo: está destinado a ser utilizado para la reinterpretación de punteros / referencias.

Lo que estás tratando de hacer no es reinterpretarlo. Si desea reinterpretar un int como un double , tendría que convertirlo en 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

Sin embargo, tenga en cuenta que, si bien 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 tiene mucho sentido en una plataforma con int y double de diferente tamaño (ya que en el caso de un double mayor, leerá 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 int más significativo para double conversión? Si es así, reinterpret_cast no te ayudará aquí.


Eso es interesante. Tal vez esté haciendo una conversión implícita de int a float antes de intentar duplicar la conversión. Los tipos int y float tienden a ser del mismo tamaño en bytes (dependiendo de su sistema, por supuesto).


Lanzar un int a un doble no requiere un lanzamiento. El compilador realizará la asignación de forma implícita.

Reinterpret_cast se utiliza con punteros y referencias, por ejemplo, convertir un int * en un double * .


Reinterpretar cast le permite reinterpretar un bloque de memoria como un tipo diferente. Esto tiene que ser realizado en punteros o referencias :

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

La otra cosa es que, de hecho, es un reparto bastante peligroso, no solo debido a valores extraños que salen como resultado, o la afirmación anterior no falla, sino porque si los tipos son de diferentes tamaños, y se reinterpreta desde ''fuente'' a Tipos de ''destino'', cualquier operación en la referencia / puntero reinterpretada accederá a bytes de sizeof(destination) . Si sizeof(destination)>sizeof(source) entonces eso irá más allá de la memoria de la variable real, matando potencialmente su aplicación o sobrescribiendo otras variables distintas del origen 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 );


Si está intentando convertir los bits de su int en la representación de un double , debe convertir la 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);


reinterpret_cast no es un reparto general. Según la sección 5.2.10.1 de la especificación C ++ 03:

Las conversiones que pueden realizarse explícitamente utilizando reinterpret_cast se enumeran a continuación. Ninguna otra conversión se puede realizar explícitamente usando reinterpret_cast.

Y no hay nada en la lista que describa la conversión entre tipos integrales y de punto flotante (o entre tipos integrales, incluso esto es ilegal reinterpret_cast<long>(int(3)); )


reinterpret_cast se utiliza mejor para los punteros. Por lo tanto, un puntero a un objeto se puede convertir en un "submarino".

Desde msdn :

El operador reinterpret_cast se puede usar para conversiones como char * to int * o One_class * Unrelated_class *, que son inherentemente inseguras.

El resultado de un reinterpret_cast no se puede usar de forma segura para otra cosa que no sea volver a su tipo original. Otros usos son, en el mejor de los casos, no portables.