Tip podatka (računarstvo)
U računarstvu i računalnom programiranju tip podatka svojstvo je podatka (često varijabli) koje kompilatoru ili interpreteru pruža informaciju o tome što će se s navedenim podatkom raditi, kakve će operacije biti dopušteno vršiti nad podatkom, na koji će se način podatak spremati i što podatak predstavlja.
Tipovi podataka dijele se na primitivne i složene.
Primitivni su tipovi podataka oni koje programski jezik zadano podržava. U većini jezika takvi se tipovi ne mogu proširivati ni redefinirati, a njihovi se operatori ne mogu preopterećivati.
Klasični primitivni tipovi podatka obično su:
- boolean - sadrži vrijednost računalne točnosti ili pogrešnosti (obično bitovi 1 ili 0)
- cijeli broj (integer) - sadrži brojeve bez decimala obično unutar vrijednosnih ograničenja
- decimalni broj s pomičnom točkom (float) - sadrži decimalni broj jednostruke preciznosti koji obično ima stalan broj ukupnih znamenki
- znak - sadrži jedan grafem ili simbol
- string - sadrži niz znakova, obično ograničen maks. duljinom ili znakom \0
Primitivni tipovi podataka mogu uključivati i složene (kompozitne) tipove za koje jezik zadano pruža podršku. Kao primjer, C ne poznaje tip podatka string, i nema definirane operacije sa stringovima.[1] C# pruža ugrađenu podršku za tip string, no sam tip je definiran kao kompozitni tip sastavljen od niza znakova (tip char).[2] JavaScript zadano podržava tip string i operacije sa stringovima, i smatra stringove primitivnim tipom podatka.[3]
Tip podatka boolean ili bool je logički tip koji obično sadrži vrijednosti true ili false (obično predstavljen brojčanim zapisom 1 ili 0, respektivno). Iako je za zapis boolean vrijednosti dovoljan jedan bit memorije, neki programski jezici koriste više od toga.[4] Npr. u JavaScriptu, boolean često zauzima 4 bajta na 32-bitnim platformama, i 8 bajtova na 64-bitnim platformama, zbog načina alokacije memorije na takvim sustavima.[5]
Neki jezici također dopuštaju implicitno pretvaranje boolean tipa u cijeli broj. Rane implementacije jezika C nisu imale zasebno definiran tip boolean, već se brojčana vrijednost 0 uzimala kao logička laž (false), a bilo koja druga brojčana vrijednost kao logička istina (true).[6] Standard jezika C imena C99 uvodi boolean kao zaseban tip podatka i dio biblioteke stdbool.h.[7] Jezik C++ podržava bool
kao ugrađeni tip podatka, a riječi "true" i "false" su rezervirane i mogu se koristiti samo u te svrhe.[8]
Svaki numerički tip podatka ima definiranu gornju i donju vrijednosnu granicu, odnosno raspon brojeva koje može prikazati. Spremanje ili prikaz brojeva van tog raspona može dovesti do pogreške pri kompilaciji, ili do neispravnog spremanja ili obrade podatka, ovisno o programskome jeziku. Vrijednosna granica je obično određena veličinom memorije koja je odvojena za spremanje tog tipa podatka (obično je gornja granica 2n gdje je n broj bitova korišten za spremanje tog podatka). Neki jezici također rezerviraju jedan bit za predznak broja, što smanjuje raspon vrijednosti takvog tipa podatka. Decimalni tipovi podataka uvelike se razlikuju u načinu spremanja vrijednosti i preciznosti istih, koje najčešće ovise o definiciji samog programskog jezika.
Niže je primjer brojevnih tipova i njihovih raspona u jeziku C++:
Tip podataka | Vrsta | Predznak | Duljina (broj bajtova)[9] | Opseg[9] | |
---|---|---|---|---|---|
1 | int | short | signed | 2 | -32.768 do 32.767 |
unsigned | 2 | 0 do 65.535 | |||
long | signed | 4 | –2.147.483.648 do 2.147.483.647 | ||
unsigned | 4 | 0 do 4.294.967.295 | |||
long long | signed | 8 | –9.223.372.036.854.775.808 do 9.223.372.036.854.775.807 | ||
unsigned | 8 | 0 do 18.446.744.073.709.551.615 | |||
2 | float | 4 | -3.4·10−38 do 3.4·1038 | ||
3 | double | 8 | -1.7·10−308 do 1.7·10308 |
Znak (char) je tip podatka koji može sadržavati jedno slovo, broj, simbol, interpunkcijski znak, kontrolni znak ili kakav drugi specijalizirani znak. Jezik C definira znak kao najmanji dodjeljivi dio memorije, obično veličine 8 bitova (1 bajt). Neki jezici imaju dodatnu podjelu znakova po veličini bajtova koje zauzimaju: jednobajtni tipovi prihvaćaju sve znakove u ASCII tablici, dok dvobajtni tipovi prihvaćaju sve Unicode znakove. Neki jezici visoke razine (Python, Ruby) nemaju zaseban tip podatka za char, već koriste stringove veličine 1.[10][11]
Znak može sadržavati broj, no znak neće imati istu numeričku vrijednost kao broj. Numerička vrijednost broja 5 je 5, dok je numerička vrijednost znaka "5" jednaka broju 53 (jer je znak za broj 5 u ASCII tablici 53. po redu). Operacija "5"+5
(nakon implicitne pretvorbe znaka "5" u broj 53) vratit će rezultat 58. Ovakva je pretvorba tipova podataka (cast) u jezicima poput C-a prihvatljiva, dok će u drugima izazvati pogrešku.
JavaScript ovakve konverzije prihvaća, ali rezultat operacija su ponekad neočekivani:
> 2+2
4
>"2" + "2"
22
>2+2-2
2
>"2"+"2"-"2"
20
>("2"+"2")-"2"
20
>"2"+("2"-"2")
20
Više slijednih znakova čini string. Stringovi se obično koriste kao podatkovna reprezentacija riječi ili teksta. Programski jezici koji nemaju podršku za stringove, umjesto istih koriste nizove (polja) znakova. Takva su polja često imutabilna. Stringovi se često delimitiraju navodnicima ili jednostrukim apostrofima.
Stringovi također mogu sadržavati brojeve (čime čine brojčani string, npr. "1234"
), no takvi stringovi nisu jednaki broju koji string predstavlja, a matematičke operacije između brojčanih stringova i brojeva (npr. "12"+28
) izazvat će pogrešku (neće doći do implicitne pretvorbe tipova podataka).
Među programskim jezicima postoje razlike u implementaciji i obradi stringova. Najjednostavniji način je stvaranje niza (polja) znakova (ponekad ograničenih fiksnom veličinom), i označavanje kraja stringa posebnim delimiterom, često znakom znakom NUL (\0
). Ovakav se string naziva "null-terminated string", ponegdje i C string (ovakav način rada koristi jezik C). Problem s ovakvom implementacijom javlja se ako string prekorači veličinu svog spremnika (ako je isti fiksne veličine):
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
o | v | o | j | e | s | t | r | i | n | g | ! | ! | ! | \0 | ||
o | v | o | j | e | v | e | ć | i | s | t | r | i | n |
Ako se dogodi prekoračenje veličine (buffer overflow), program će nastaviti čitati susjednu memoriju dok ne naiđe na znak \0
, što može dovesti do pogrešaka u radu, naročito ako program pokuša pristupiti memoriji koju nema pravo čitati. Operacijski sustav takve programe može srušiti kao mjeru prevencije štete.
Neki programski jezici (C++ i Java) koriste \0
za kraj stringova, no unutar standardnih biblioteka imaju definirane zasebne klase za obradu i spremanje stringova koji sprječavaju problem prekoračenja veličine (obično alokacijom dodatne memorije po potrebi). C++ za tu svrhu koristi klasu std::string
, dok Java koristi Java.lang.String
.
Među jezicima također postoji razlika u mogućnosti naknadne promjene sadržaja varijabli tipa string. Stringovi kojima nije moguće promijeniti veličinu ni sadržaj zovu se imutabilni (immutable). Za promjenu sadržaja imutabilnog stringa potrebno je direktno mijenjati računalnu memoriju (npr. C funkcijom memcpy, pri čemu treba iznimno paziti na problem prekoračenja veličine i prepisivanja susjedne memorije ako je novi string veći od spremnika). Sigurniji način rada s imutabilnim stringovima je deklaracija nove varijable ili objekta koji sadrži vrijednost novog stringa. Jezici poput JavaScripta,[12] Lue[13] i Pythona[14] koriste konstante (imutabilne) stringove. Promjenjive stringove koriste npr. C++,[15] Perl[16] i Ruby.[17]
Pokazivač ili referenca je tip objekta koji sprema memorijsku adresu neke varijable, konstante ili objekta. U proceduralnom programiranju, pokazivači spremaju podatak o točki ulaska u potprogram. Također se koriste za povezivanje programa i vanjskih resursa, poput DLL biblioteka (tad se nazivaju handle). Pokazivači dopuštaju čitanje i promjenu varijable na koju pokazuju. Dodjela memorijske adrese pokazivaču naziva se referenciranje. Pristup ili promjena vrijednosti varijable na dodijeljenoj adresi naziva se dereferenciranje.
Neki programski jezici podržavaju više različitih tipova pokazivača. C++ u sklopu biblioteke memory pruža pristup različitim tipovima tzv. pametnih pokazivača, originalno osmišljenim kao zamjena za garbage collector kojim jezici poput C# i Jave automatski upravljaju memorijom i objektima. C++ podržava:
- auto_ptr: svaki pametni pokazivač tog tipa isključivi je vlasnik jednog dinamički alociranog objekta. Drugi pokazivač ovog tipa referenciran na isti objekt semantikom kopiranja (pozivom kopirnog konstruktora) preuzima vlasništvo nad objektom, čime prvi pokazivač postaje nedefiniran (pokazuje na memorijsku lokaciju na kojoj se objekt više ne nalazi). Uvođenjem unique_ptr, ovaj tip pokazivača ulazi u zastaru i nije ga preporučljivo koristiti.[18]
- unique_ptr: dopušta preuzimanje vlasništva nad objektom samo pomoću semantike prijenosa (pozivom prijenosnog konstruktora), čime se prvi pokazivač automatski postavlja na vrijednost
NULL
, što sprječava nedefinirana ponašanja.[19] - shared_ptr: stvaranjem ovog tipa pokazivača stvara se kontrolni objekt koji automatski prati koliko drugih shared_ptr i weak_ptr pokazivača koristi alocirani objekt. Nakon što svi shared_ptr pokazivači prestanu pokazivati na objekt, objekt se dealocira iz memorije (uništava). Kontrolni objekt postoji dok god postoji weak_ptr koji pokazuje na objekt (neovisno postoji li objekt ili je uništen). Kontrolni se objekt uništava tek kad brojač weak_ptr pokazivača padne na nulu.[20]
- weak_ptr: ovaj tip pokazivača dopušta uništavanje objekta iako postoje pokazivači na njega. Koristi se za sprječavanje kružnih ovisnosti objekata (A->B->C->A).[21]
U novijim programskim jezicima koji teže modelu univerzalne obrade podataka, funkcije je moguće proslijediti kao argumente drugim funkcijama (jezici koji to podržavaju kažemo da podržavaju funkcije prve klase). Klasično se samo podatci mogu slati kao argumenti funkcijama, pa je u svrhe facilitacije prvoklasnih funkcija uveden funkcijski tip podatka koji omogućava ovakve interakcije.
Niže je dan prikaz sintakse funkcijskog tipa nekolicine programskih jezika, uz primjer deklaracije funkcije koja omogućuje matematičku kompoziciju: f(g(x)), gdje se rezultat funkcije g uzima kao argument pri izračunu funkcije f. Parametarski polimorfizam vrsta je ad-hoc polimorfizma, što je osnova generičkog programiranja, koje omogućava pisanje tzv. funkcijskih predložaka koje jednako rade neovisno o tipu podatka koji prime.
Jezik | Zapis | Funkcijski potpis (deklaracija) | |
---|---|---|---|
S prvoklasnim funkcijama i
parametarskim polimorfizmom |
C# | Func<α1,α2,...,αn,ρ>
|
Func<A,C> compose(Func<B,C> f, Func<A,B> g);
|
Haskell | α -> ρ
|
compose :: (b -> c) -> (a -> b) -> a -> c
| |
OCaml | α -> ρ
|
compose : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c
| |
Scala | (α1,α2,...,αn) => ρ
|
def compose[A, B, C](f: B => C, g: A => B): A => C
| |
Standard ML | α -> ρ
|
compose : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c
| |
Swift | α -> ρ
|
func compose<A,B,C>(f: B -> C, g: A -> B) -> A -> C
| |
Rust | fn(α1,α2,...,αn) -> ρ
|
fn compose<A, B, C>(f: fn(A) -> B, g: fn(B) -> C) -> fn(A) -> C
| |
S prvoklasnim funkcijama, bez
parametarskog polimorfizma |
Go | func(α1,α2,...,αn) ρ
|
var compose func(func(int)int, func(int)int) func(int)int
|
C++, Objective-C,
s blokovima |
ρ (^)(α1,α2,...,αn)
|
int (^compose(int (^f)(int), int (^g)(int)))(int);
| |
Bez prvoklasnih funkcija
i parametarskog polimorfizma |
C | ρ (*)(α1,α2,...,αn)
|
int (*compose(int (*f)(int), int (*g)(int)))(int);
|
C++11 | Nije jedinstven
|
function<function<int(int)>(function<int(int)>, function<int(int)>)> compose;
|
Ako gledamo potpis funkcije u npr. jeziku C#, tip funkcije compose
je zapravo Func<Func<A,B>,Func<B,C>,Func<A,C>>
.
Nulabilni tipovi mogućnost su nekih programskih jezika koji dopuštaju da se vrijednost neke varijable postavi na posebnu vrijednost NULL umjesto dozvoljenih vrijednosti toga podatkovnog tipa. Vrijednost NULL obično predstavlja vrijednost koja nedostaje ili je neispravna (primjerice izvan očekivanog raspona). U određenim jezicima, primjerice C#, primitivni tipovi podataka obično ne mogu poprimiti NULL vrijednost, ali pripadajući nulabilni tip (primjerice Nullable Integer - int?
) može. Znak ? nakon deklaracije tipa podatka čini tip nulabilnim, odnosno sposobnim poprimiti vrijednost NULL.
Varijabla tipa Boolean može imati vrijednost istina ili laž, dok nulabilni Boolean dodaje i mogućnost predodžbe neodlučene ili nedefinirane vrijednosti.
Pokazivači i reference smiju se uvijek postaviti na vrijednost NULL neovisno o tipu, što označava da referenca ne vodi nikamo, nema dodijeljenu memorijsku adresu i nije vezana uz objekt.
Pokušaj izvođenja matematičkih i logičkih operacija nad varijablama koje su postavljene na NULL rezultirat će pogreškom te izbacivanjem iznimke (obično vrste InvalidOperation) ili padom programa.
Pokušaj dereferenciranja pokazivača ili pristupanje vrijednostima ili svojstvima varijable ili objekta koji su postavljeni na NULL rezultirat će padom programa zbog pokušaja pristupa nedozvoljenoj ili nepostojećoj memoriji (segmentacijska pogreška).[22] Neki jezici, poput Jave, Lispa ili C# koriste sakupljanje smeća, što će izbjeći direktnu segmentacijsku pogrešku[23] ali će baciti iznimku klasnog tipa NullPointerException koja može dovesti do pada programa. Jezik C++ podržava eksplicitno bacanje ručno stvorenih iznimki, no pokušaj pristupa NULL vrijednosti smatra se neodređenim ponašanjem[24], pa će program pasti bez iznimke.
- ↑ Data Types in C. GeeksforGeeks (engleski). 30. lipnja 2015. Inačica izvorne stranice arhivirana 20. prosinca 2020. Pristupljeno 31. prosinca 2020.
- ↑ dotnet-bot. String Class (System). docs.microsoft.com (engleski). Inačica izvorne stranice arhivirana 9. ožujka 2021. Pristupljeno 31. prosinca 2020.
- ↑ String - JavaScript | MDN. developer.mozilla.org. Inačica izvorne stranice arhivirana 4. siječnja 2021. Pristupljeno 31. prosinca 2020.
- ↑ [expr.sizeof]. eel.is. Inačica izvorne stranice arhivirana 15. siječnja 2021. Pristupljeno 31. prosinca 2020.
- ↑ Memory size of Javascript Boolean. DEV Community (engleski). Inačica izvorne stranice arhivirana 9. ožujka 2021. Pristupljeno 31. prosinca 2020.
- ↑ Brian W. Kernighan, Dennis M. Ritchie. str. 41.. The C Programming Language. prvo izdanje izdanje. Prentice Hall. Englewood Cliffs, New Jersey. ISBN 0-13-110163-3
- ↑ Boolean type support library. devdocs.io. Inačica izvorne stranice arhivirana 2. veljače 2019. Pristupljeno 15. listopada 2020.
- ↑ Bool data type in C++. GeeksforGeeks. Inačica izvorne stranice arhivirana 18. rujna 2020. Pristupljeno 15. listopada 2020.
- ↑ a b corob-msft. Data Type Ranges. docs.microsoft.com (engleski). Inačica izvorne stranice arhivirana 9. ožujka 2021. Pristupljeno 31. prosinca 2020.
- ↑ Python Strings. w3schools.com. Inačica izvorne stranice arhivirana 2. siječnja 2021. Pristupljeno 1. siječnja 2021.
- ↑ Class: String (Ruby 2.5.3). ruby-doc.org. Inačica izvorne stranice arhivirana 12. studenoga 2020. Pristupljeno 1. siječnja 2021.
- ↑ Immutability in JavaScript - SitePoint. sitepoint.com (engleski). Inačica izvorne stranice arhivirana 24. siječnja 2021. Pristupljeno 1. siječnja 2021.
- ↑ Programming in Lua : 2.4. lua.org. Inačica izvorne stranice arhivirana 2. veljače 2021. Pristupljeno 1. siječnja 2021.
- ↑ Leung, Wendy. 9. lipnja 2019. Mutability and Immutability in Python — Let’s Break It Down. Medium (engleski). Inačica izvorne stranice arhivirana 28. svibnja 2020. Pristupljeno 1. siječnja 2021.
- ↑ Lemire, Author Daniel. Are your strings immutable?. Daniel Lemire's blog (engleski). Inačica izvorne stranice arhivirana 28. veljače 2021. Pristupljeno 1. siječnja 2021.
- ↑ Are Perl strings immutable?. Stack Overflow. Inačica izvorne stranice arhivirana 29. srpnja 2015. Pristupljeno 1. siječnja 2021.
- ↑ Understanding Mutable Objects & Frozen Strings. RubyGuides (engleski). 3. siječnja 2016. Inačica izvorne stranice arhivirana 2. prosinca 2020. Pristupljeno 1. siječnja 2021.
- ↑ std::auto_ptr - cppreference.com. en.cppreference.com. Inačica izvorne stranice arhivirana 10. travnja 2021. Pristupljeno 1. siječnja 2021.
- ↑ std::unique_ptr - cppreference.com. en.cppreference.com. Inačica izvorne stranice arhivirana 12. studenoga 2020. Pristupljeno 1. siječnja 2021.
- ↑ std::shared_ptr - cppreference.com. en.cppreference.com. Inačica izvorne stranice arhivirana 28. prosinca 2020. Pristupljeno 1. siječnja 2021.
- ↑ std::weak_ptr - cppreference.com. en.cppreference.com. Inačica izvorne stranice arhivirana 16. siječnja 2021. Pristupljeno 1. siječnja 2021.
- ↑ Debugging Segmentation Faults and Pointer Problems - Cprogramming.com. www.cprogramming.com. Inačica izvorne stranice arhivirana 10. srpnja 2022. Pristupljeno 14. ožujka 2022.
- ↑ Dhurjati, Dinakar; Kowshik, Sumant; Adve, Vikram; Lattner, Chris. 2003. Memory safety without runtime checks or garbage collection. Proceedings of the 2003 ACM SIGPLAN conference on Language, compiler, and tool for embedded systems - LCTES '03 (engleski). ACM Press. San Diego, California, USA. : 69. doi:10.1145/780732.780743. ISBN 978-1-58113-647-0. Inačica izvorne stranice arhivirana 16. svibnja 2022. Pristupljeno 14. ožujka 2022.
- ↑ Undefined behavior - cppreference.com. en.cppreference.com. Inačica izvorne stranice arhivirana 1. travnja 2022. Pristupljeno 14. ožujka 2022..
undefined behavior - [...], null pointer dereference, [...]
Zajednički poslužitelj ima još gradiva o temi tip podatka (računarstvo) |
|