Pretvaranje tipova podataka
U računarstvu, pretvaranje tipova podataka (engl. type conversion,[1][2] type casting,[1][3] type coercion[3] ili type juggling[4][5] ) način je promjene tipa podatka neke varijable unutar programskog koda. Pretvorba može biti implicitna (automatska) ili eksplicitna (zatražena),[1][6] a novi podatak može biti pretvoren iz jednog oblika u drugi, ili ponovno interpretiran kao oblik drugog tipa.[6][7] Pretvorba je moguća i nad primitivnim i nad složenim tipovima.
Svaki programski jezik ima vlastita pravila o pretvaranju tipova podataka. Jezici stroge tipizacije rade implicitne pretvorbe u iznimnim slučajevima i ne preporučaju eksplicitne pretvorbe, dok jezici slabe tipizacije izvode mnoge implicitne pretvorbe, što može dovesti do neočekivanih grešaka pri izvođenju.
Implicitna pretvorba[uredi | uredi kôd]
Implicitno pretvaranje tipova kompilator radi automatski (ako su definirana pravila pretvorbe) kako bi izveo pojedine operacije nad podatcima.
Primjerice, kako bi se izračunao izraz 5 + 0.1, kompilator će napraviti implicitnu pretvorbu cijelog broja (integer) 5 u decimalni broj (float) 5.0, zbrojit će dva decimalna broja i vratit će rezultat kao decimalan broj.
U ovakvim izrazima miješanih tipova, vrijednosti jednog ili više pod-tipova mogu pri izvođenju se implicitno pretvoriti u nad-tip kako bi se izvele zatražene operacije.
Sljedeće je ispravan C kod:
double d;
long l;
int i;
if (d > i) d = i;
if (i > l) l = i;
if (d == l) d *= 2;
Iako su d, l, i i različiti tipovi podataka, pri svakoj usporedbi ili dodjeli dogodit će se implicitna pretvorba u dva jednaka tipa podatka. Ovo ponašanje može imati neočekivane posljedice i može dovesti do pogrešaka ili gubitka podataka.
- pretvaranje iz float u int dovodi do zaokruživanja i gubitka decimala
- pretvaranje iz double u float dovodi do zaokruživanja prema više
- pretvaranje iz long u int dovodi do gubitka preciznosti
- neočekivano, pretvaranje iz int u float može dovesti do pogrešaka pri pretvorbi velikih brojeva, što demonstrira sljedeći kod:
#include <stdio.h>
int main(void)
{
int i_value = 16777217;
float f_value = 16777216.0;
printf("Cijeli broj je: %d\n", i_value);
printf("Decimalni broj je: %f\n", f_value);
printf("Jesu li jednaki?: %d\n", i_value == f_value);
}
Ako se kod izvodi na kompilatoru koji implementira float kao decimalni broj jednostruke preciznosti sukladno IEEE standardu, i procesoru koji promiče cijeli broj na barem 32 bita, gornji će kod vratiti sljedeći neobičan ispis:
Cijeli broj je: 16777217 Decimalni broj je: 16777216.000000 Jesu li jednaki?: 1
U zadnjoj liniji broj 1 predstavlja zaključak "tvrdnja je istinita" (odnosno brojevi su jednaki). Ovo se ponašanje događa jer se cijeli broj implicitno pretvara u decimalni broj jednostruke preciznosti (kako je opisano standardom IEEE 754). Pretvorba uzrokuje gubitak preciznosti (koristi se jednak broj bitova za prikaz cijelog broja, i za prikaz decimalnog broja, pa stoga decimalni broj može prikazati manji raspon vrijednosti jer se dio bitova mora odvojiti za decimale).
Promicanje tipova[uredi | uredi kôd]
Poseban slučaj implicitne pretvorbe tipova je promicanje (unaprjeđenje, promocija) tipova, gdje kompilator automatski proširuje binarni oblik objekata cjelobrojnog ili decimalnog tipa. Promicanjem vrijednost varijable nikad ne gubi preciznost, a sama vrijednost spremljena u memoriji ne mijenja se zbog promocije.
Promicanje se događa ako je zapis tipa podatka manji od najmanjeg tipa koji aritmetičko-logička jedinica računalnog procesora može obraditi. Također se događa prije obrade logičkih (boolean) operacija kao preduvjet njihova izvođenja. Jezici C i C++ implicitno promiču tipove boolean (istina/laž), char (znak), w_char_t (Unikodni UTF-16 znak), enum (enumeracije) i short int (cijeli broj smanjena raspona) u tip int (cijeli broj), i također tip float (decimalni broj jednostruke preciznosti) u double (decimalni broj dvostruke preciznosti).
Eksplicitna pretvorba[uredi | uredi kôd]
Eksplicitnu pretvorbu autor programskog koda mora zatražiti.
double da = 3.3;
double db = 3.3;
double dc = 3.4;
int rezultat = (int)da + (int)db + (int)dc; // rezultat = 9
// da se koristila implicitna konverzija (kod "rezultat = da + db + dc"), rezultat bi bio 10
Postoji nekoliko vrsta eksplicitne pretvorbe.
- provjerena (checked)
- Prije izvođenja pretvorbe vrši se provjera može li ciljni tip spremiti izvornu vrijednost. Ako ne može, program vraća pogrešku pri izvođenju.
- neprovjerena (unchecked)
- Ne izvodi se provjera. Ako ciljni tip ne može spremiti vrijednost, rezultat nije definiran (tip podatka je undefined).
- uzorak bitova (bit pattern)
- Bitovi izvornog podatka u memoriji kopiraju se na mjesto nove varijable. Bitovi se interpretiraju sukladno odredišnom tipu.
Objektno orijentirani jezici podržavaju i radnju suprotnu promociji: referenca bazne klase može se pretvoriti u tip jedne od njenih pod-klasa.
C# i C++[uredi | uredi kôd]
U jeziku C#, pretvorba tipova može biti sigurna ili nesigurna.[8]
Animal animal = new Cat();
// sigurne pretvorbe:
Bulldog b = (Bulldog) animal;
// ako je animal tipa Bulldog,
// onda je tip podatka varijable animal jednaka Bulldog,
// u suprotnom vrati iznimku
b = animal as Bulldog;
// ako je animal tipa Bulldog,
// onda je b = (Bulldog) animal (isto kao iznad)
// u suprotnom b = null
// nesigurna pretvorba
animal = null;
b = animal as Bulldog; // b = null
U jeziku C++ sličan se učinak može postići korištenjem operatora dinamičke pretvorbe:
Animal* animal = new Cat;
Bulldog* b = static_cast<Bulldog*>(animal);
// radi samo kao su klase Animal ili Bulldog derivirane jedna druge,
// u suprotnom greška pri kompilaciji
b = dynamic_cast<Bulldog*>(animal);
// ako je animal tipa Bulldog vraća b = (Bulldog*) animal,
// u suprotnom vraća b = null-pointer
Bulldog& br = static_cast<Bulldog&>(*animal);
// isto kao iznad, ali pri neuspjehu se vraća iznimka NullPointerException
animal = nullptr;
b = dynamic_cast<Bulldog*>(animal); // b = null-pointer
delete animal;
Izvori[uredi | uredi kôd]
- ↑ a b c Mehrotra, Dheeraj. 2008. S. Chand's Computer Science. str. 81–83. ISBN 978-8121929844
- ↑ Programming Languages - Design and Constructs. 2013. str. 35. ISBN 978-9381159415
- ↑ a b Reilly, Edwin. 2004. Concise Encyclopedia of Computer Science. str. 82, 110. ISBN 0470090952
- ↑ Fenton, Steve. 2017. Pro TypeScript: Application-Scale JavaScript Development. str. xxiii. ISBN 978-1484232491
- ↑ PHP: Type Juggling - Manual. php.net. Pristupljeno 27. siječnja 2019.
- ↑ a b Olsson, Mikael. 2013. C++ Quick Syntax Reference. str. 87–89. ISBN 978-1430262770
- ↑ Kruse, Rudolf; Borgelt, Christian; Braune, Christian; Mostaghim, Sanaz; Steinbrecher, Matthias. 16. rujna 2016. Computational Intelligence: A Methodological Introduction. str. 269. ISBN 978-1447172963
- ↑ Mössenböck, Hanspeter. 25. ožujka 2002. Advanced C#: Checked Type Casts (PDF). Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik. str. 5. Pristupljeno 4. kolovoza 2011. at C# Tutorial
|