Canvi de tipus de dades en C
Objectius
- Comprendre el concepte de canvi de tipus de dades.
- Conèixer les regles del canvi de tipus implícit.
- Saber quan i com s’han de fer canvis explícits de tipus.
Introducció
Molt sovint cal canviar el tipus de dades d’una expressió. En la majoria de casos, el compilador de C realitza aquestes conversions de manera totalment automàtica i transparent al programador. L’estàndard del llenguatge C (ISO/IEC 9899) defineix les regles utilitzades per a fer aquests canvis. Encara que no és necessari saber aquestes normes de memòria, sí que és important tenir nocions de quines són, per a evitar tenir sorpreses en el funcionament dels nostres programes i saber quan cal fer la conversió de tipus de forma explícita. En aquesta guía se citen aquestes normes i se’n posen alguns exemples.
1. Regles de conversió
Els canvis automàtics de tipus de dades representen una simplificació de cara al compilador de C, que no sap com operar amb dos elements de tipus diferents i, per tant, canvia el tipus d’un d’ells per a poder operar amb elements del mateix tipus. També tenen un segon objectiu, que és facilitar la feina del programador, ja que no ha de fer aquests canvis de manera explícita en aquells casos inequívocs.
A continuació es mostra una llista simplificada de les normes de l’estàndard, que és suficient de cara a l’assignatura, però que no cobreix tots els possibles casos. Les regles es mostren en l’ordre d’aplicació:
- Si una operació involucra dos operands i un d’ells és de tipus long double, l’altre es converteix en long double.
- Si una operació involucra dos operands i un d’ells és de tipus double, l’altre es converteix en double.
- Si una operació involucra dos operands i un d’ells és de tipus float, l’altre es converteix en float.
- En la majoria dels casos, els valors de tipus char i short int es converteixen en int immediatament.
- Si una operació involucra dos operands i un d’ells és de tipus long int, l’altre es converteix en long int.
- Si una expressió involucra tant enters amb signe com sense signe, la situació es complica. Si l’operand sense signe té una capacitat de representació menor (per exemple, tenim un unsigned int i un long int), pel que el tipus amb signe té capacitat pera representar tots els valors del tipus sense signe, el valor sense signe es converteix en el tipus amb signe i el resultat adopta aquest tipus amb signe. En cas contrari (és a dir, si el tipus amb signe no pot representar tots els valors del tipus sense signe, com per exemple unsigned short int i un int), tots dos valors es converteixen en un tipus sense signe comú i el resultat té aquest tipus sense signe.
- Finalment, quan s’assigna un valor a una variable mitjançant l’operador d’assignació, aquest es converteix automàticament al tipus de la variable, si tant el valor com la variable tenen tipus aritmètic (és a dir, nombre enter o punt flotant).
2. Canvi explícit de tipus de dades
Quan ens trobem amb casos no coberts per les regles anteriors, o simplement no ens interessa que aquestes s’apliquin, caldrà fer el canvi de tipus de dades de forma explícita. En els casos en què s’apliqui la regla 6 anteriorment citada, també és aconsellable fer un canvi explícit per a evitar resultats inesperats.
En els casos que ens interessi fer un canvi de tipus de dades o cast, el farem posant el tipus destinació entre parèntesi, actuant com un operador unari, la qual cosa significa que afectarà el que tingui just a la seva dreta. Fixeu-vos en el següent exemple:
[Exemple 09_01]
int main(int argc, char** argv) {
int a = 1;
int b = 2;
float r;
r = a / b;
printf("%f", r);
return 0;
}
Quin resultat esperaríem que es mostrés per pantalla? Segurament ens esperaríem que la variable r tingués el valor 0.5, però realment tindrà el valor 0. Si analitzem l’expressió a/ b, ens adonarem que tant a com b són enters i, per tant, l’operació és una divisió entera que té com a resultat 0. Després tenim una assignació a una variable real que, seguint la regla 7, es converteix en real i es guarda a la variable r.
Si el que volem fer és que la divisió no sigui entera, hauríem de fer un canvi explícit de tipus de dades:
[Exemple 09_02]
int main(int argc, char** argv) {
int a = 1;
int b = 2;
float r;
r = (float)a / (float)b;
printf("%f", r);
return 0;
}
En aquest exemple, el canvi de tipus (float) s’aplica tant a a com a b, per tant, la divisió serà entre reals i el resultat és 0.5, que és el que esperaríem. De fet, tenint en compte la regla 3, solament que canviem un dels tipus ja seria suficient, ja que el compilador faria l’altre canvi de manera automàtica. Per tant, el codi següent també donaria el resultat esperat:
[Exemple 09_03]
int main(int argc, char** argv) {
int a = 1;
int b = 2;
float r;
r = (float)a / b;
printf("%f", r);
return 0;
}
Resum
En aquesta guia hem vist com es fan els canvis de tipus de dades en el llenguatge C. Hem vist que en la majoria dels casos el compilador els fa automàticament seguint unes regles, però que en alguns casos hem de fer el canvi de forma explícita.