Cuando en una expresión en C++ intervienen operandos de
distinto tipo, los datos se convierten de forma temporal al operando de mayor
precisión para realizar la operación.
Cuando
a un variable se le asigna un valor que no es de su tipo, C++ convierte el
valor de la derecha al tipo de la variable a la que se le va a asignar siempre
que no haya pérdida de información.
Si
se produce pérdida de información el compilador avisará de ello.
En
una asignación de tipos distintos puede ocurrir que:
1. Un valor real
(tipo double o float) puede truncarse (pierde la parte decimal) si se asigna a una
variable entera.
2. Un valor de
tipo double puede ser redondeado si se asigna a una variable de tipo float.
3. Un valor de
tipo entero puede ser modificado si se asigna a una variable entera de menor
precisión o a una variable de tipo char. Algunos de los bits más significativos
pueden perderse.
Por ejemplo, dadas las siguientes declaraciones de
variables:
long int k;
unsigned char m;
double p;
int n, q;
Para calcular la siguiente expresión: q = k + m * n / p el proceso es el siguiente:
1. Se realiza la multiplicación m * n. Para ello se
convierte m (unsigned char) a int y a continuación se multiplica por n. El
resultado es de tipo int.
2. Se realiza la división. Como p es de tipo double, el
resultado anterior de multiplicar m * n que es de tipo int se convierte a
double y se hace la división. El resultado es de tipo double.
3. Se realiza la suma. Para ello se convierte k (long) a
double y se suma al resultado de la división anterior. El resultado de la suma
es de tipo double.
4. El último paso es asignar el resultado de tipo double
a q que es de tipo int. En este caso el resultado se pasa a tipo int por
truncamiento, o sea, eliminando la parte fraccionaria. En este caso de pérdida
de precisión el compilador avisará de ello.
Estas conversiones las realiza C++ de forma automática. Esta
conversión se conoce como conversión implícita.
En algunos casos necesitaremos asignar datos de un tipo a
variables que son de otro tipo y que el compilador no nos avise ello y permita
realizar la operación. En ese caso utilizaremos la conversión explícita o casting.
En general, el uso del casting es obligatorio
cuando se hacen asignaciones con pérdida de precisión.
Un casting lo podemos hacer, siguiendo el modelo de
C, de dos formas:
(tipo) expresión
ó
tipo(expresión)
Por ejemplo:
float a = 10.2;
int b, c = 5;
b = (int)(a + c); // convierte a int por truncamiento. Asigna a
b el valor 15
c = int (a); // asigna a c el valor 10
Si en las instrucciones anteriores no realizamos el
casting el compilador avisará de la pérdida de precisión y no nos dejará
hacerlo.
Otro
ejemplo. Dadas las variables:
int i = 7;
float f = 8.5;
La expresión (i + f) % 4 no es válida, ya que (i + f) produce
un resultado en coma flotante.
Esto se puede solucionar con un casting:
((int) (i + f))
% 4.
Sea ahora la expresión ((int) f) % 3, es una expresión válida, que da como
resultado el valor 2, pero debemos tener en cuenta que lo que se convierte en
entero es el valor de f, y sólo para esta expresión, ya que después f sigue teniendo el valor 8.5.
Un casting también puede ser considerado como un operador unitario.
Además
de esta forma de realizar un casting que es la tradicional de C, C++ incorpora 4 nuevos
operadores para realizar un casting de forma explícita:
static_cast<tipo>(expresión)
Convierte el tipo de la expresión al tipo indicado.
Se utiliza para realizar conversiones entre tipos
relacionados, por ejemplo entre un float y un int.
const_cast<tipo>(expresión)
Convierte el tipo de la expresión al tipo indicado.
Se utiliza para eliminar la acción del calificador const sobre la expresión.
dynamic_cast<tipo>(expresión)
Convierte el tipo de la expresión al tipo indicado.
Se utiliza para realizar conversiones verificadas durante
la ejecución, examinando el tipo del objeto que convierte.
Si la conversión es entre punteros y durante la ejecución
no se puede realizar, devuelve un cero (puntero nulo).
reinterpret_cast<tipo>(expresión)
Convierte el tipo de la expresión
al tipo indicado.
Se utiliza para realizar conversiones entre tipos no
relacionados, por ejemplo, conversiones double * a int * que static_cast no
permite.
Por ejemplo:
float a = 10.2F;
int b, c = 5;
b =
static_cast<int>(a + c); // Asigna a b el valor 15
c = static_cast<int>(a); // asigna a c el valor 10
entonces cual es la firencia entre "(int)" con un "static_cast", para que en c++ se hace otro, que hace lo mismo que el primero???, gracias por el aporte de antemano.
ResponderEliminarEl casting c++ introduce seguridad en la conversión. El casting estilo C te deja hacer casi cualquier cosa y realizar conversiones entre tipos no relacionados sin ningún tipo de aviso. El casting c++ entre tipos no relacionados lo debes indicar expresamente, asegurándote de esa forma que es eso lo que realmente quieres hacer.
ResponderEliminarPor ejemplo:
float a = 123.456;
char *c = (char*)&a; //compila perfectamente
char *d = static_cast<char *>(&a); //error de compilación al intentar convertir un float* a un char*
Para hacer esta operación tenemos que escribir:
char *d = reinterpret_cast<char *>(&a);
Con esto estamos indicando que realmente es esa la operación que queremos hacer
Buen aporte, la aclaracion, me ha ayudado
EliminarHola Enrique, qué debo de entender por Tipo de Datos Relacionados y No Relacionados ?
ResponderEliminarGracias de antemano.
Saludes
good
ResponderEliminar