Varijable i tipovi podataka
Što je varijabla i kako je koriste micro:bit i Arduino: tipovi int, long, float, char i bool, njihovi rasponi, const te česte greške s brojevima.
Kutijica s imenom
Program mora pamtiti mnogo toga: koliko bodova imaš, koliko ti je života ostalo, traje li igra još. Za to služi varijabla: kutijica s imenom u koju program spremi jedan podatak.

Ime kutijice ostaje isto, a ono što je u njoj program smije mijenjati dok radi. Zato se i zove varijabla: na latinskom variare znači mijenjati.
S varijablom program radi tri stvari:
- Napravi je i da joj ime, na primjer bodovi.
- Spremi u nju vrijednost. Ono što je prije bilo u kutijici nestane, jer kutijica pamti samo zadnju vrijednost.
- Pročita što je u njoj, na primjer da broj bodova prikaže na zaslonu.
Na kojem jeziku pišemo program za Arduino?
Program za Arduino pišemo u programskom jeziku C++ (čita se ce plus plus). C++ je nastao početkom 1980-ih kao nadogradnja jezika C, a danas se u njemu pišu igre, preglednici i programi za automobile i rakete.
Arduino jeziku C++ dodaje gotove funkcije, kao pinMode(), digitalWrite() i delay(), i dvije funkcije koje svaki program mora imati, setup() i loop(). Pravi program u jeziku C++ počinje funkcijom main(). Arduino je napiše sam: ona jednom pozove setup(), a zatim loop() ponavlja zauvijek.
I blokovi u MakeCodeu su program u pravom programskom jeziku, JavaScriptu. Na vrhu MakeCodea klikni JavaScript, ili u izborniku pokraj njega Python, pa ćeš vidjeti isti program napisan riječima.
Vrste podataka
U jednu varijablu stane samo jedna vrsta podatka:
- broj, na primjer broj bodova ili temperatura;
- tekst, na primjer ime igrača;
- istina ili laž: true (da) ili false (ne), na primjer traje li igra.
MakeCode vrstu prepozna sam, po prvoj vrijednosti koju spremiš u varijablu. Ako u bodovi na početku spremiš 0, to je varijabla za brojeve, pa u nju poslije spremaj samo brojeve.
Kako se varijable koriste na micro:bitu, piše u odjeljku Varijable u MakeCodeu, a za Arduino radionicu je odjeljak Varijable u Arduino programu.
Varijable u MakeCodeu
Varijable su u kategoriji Variables:
- Klikni Make a Variable…, upiši ime i klikni OK.
- Blokom set bodovi to 0 spremiš vrijednost. Najčešće ga staviš u on start, da igra počne od nule.
- Blok change bodovi by 1 poveća vrijednost za 1. S −1 je smanji, kao kad igrač izgubi život.
- Okrugli blok bodovi pročita vrijednost. Staviš ga u neki drugi blok, na primjer u show number.
Varijable smo prvi put koristili u lekcijama Moj prvi program u MakeCodeu i Kako naš program razmišlja?, za bodove. U lekciji Životi i uvjeti varijabla zivoti broji unatrag, a igraTraje pamti samo true ili false. U Radio igrama varijabla protivnik na početku ima vrijednost −1, jer takav znak ne postoji: tako program zna da protivnikov znak još nije stigao.
Dobro ime za varijablu
- Neka ime kaže što je u varijabli: bodovi, a ne x. Za tjedan dana nećeš se sjećati što je bio x.
- Bez razmaka i bez slova č, ć, đ, š i ž: zivoti, igraTraje. Kad ime ima više riječi, svaku novu riječ započni velikim slovom.
- Velika i mala slova su različita: bodovi i Bodovi su dvije različite varijable.
Varijable u Arduino programu
Od ovog mjesta stranica je za Arduino radionicu.
Kako napraviti varijablu
U C++ programu varijablu napravimo jednim retkom. Napišemo kojeg je tipa, kako se zove i, ako želimo, što je u njoj na početku:
int bodovi = 0; // tip, ime i početna vrijednost
bool igraTraje = false; // istina ili laž
float napon = 4.85; // decimalni broj: s točkom, a ne sa zarezom
To se zove deklaracija. Poslije ime pišemo bez tipa:
bodovi = 10; // spremi 10, a stara vrijednost nestane
bodovi = bodovi + 1; // pročitaj, dodaj 1 i spremi natrag: sada je 11
bodovi++; // isto, kraće: 12
bodovi += 5; // dodaj 5: 17
Znak = ne znači usporedbu jednakosti, nego spremi: vrijednost s desne strane spremi u varijablu na lijevoj. Zato bodovi = bodovi + 1 nije greška u računu. Jesu li dvije vrijednosti jednake, pitamo sa ==.
= nije isto što i ==
if (bodovi = 10) ne pita je li bodovi jednako 10, nego u bodovi spremi 10. Uvjet je tada uvijek ispunjen, a stari broj bodova je izgubljen. Prevoditelj to ne javi kao grešku, pa u uvjetu uvijek provjeri da su napisana dva znaka jednakosti: if (bodovi == 10).
Za imena vrijede ista pravila kao u MakeCodeu, i još nekoliko:
- Ime smije imati slova, brojke i podvlaku
_, ali ne smije početi brojkom:led2može,2ledne može. Slova č, ć, đ, š i ž Arduino u imenima ne prihvaća (pogledaj lekciju Semafor za automobile i pješake). - Ime ne smije biti riječ koju C++ već koristi, kao
int,ifilifor. - Izbjegavaj imena Arduino funkcija i funkcija jezika C, kao
time,random,linkilisignal. Na nekim Arduinima takvo ime izazove grešku pri prevođenju.
Tipovi podataka
Svaki tip zauzme zadan broj bajtova memorije, pa u njega stanu samo brojevi iz zadanog raspona. Na Arduinu Uno R3, Nanu i Megi, koji imaju 8-bitni mikrokontroler, izgleda ovako (jedan kvadratić je jedan bit):

| Tip | Bajtova | Raspon | Za što ga koristimo |
|---|---|---|---|
bool | 1 | true ili false | da ili ne: je li tipkalo pritisnuto, traje li igra |
char | 1 | −128 do 127 | jedan znak, na primjer 'A' ili '#' |
byte | 1 | 0 do 255 | mali brojevi i bajtovi, na primjer redak slike na LED matrici |
int | 2 | −32 768 do 32 767 | većina brojeva: pinovi, brojači, analogRead() |
unsigned int | 2 | 0 do 65 535 | cijeli brojevi bez predznaka, do 65 535 |
long | 4 | −2 147 483 648 do 2 147 483 647 | veliki cijeli brojevi |
unsigned long | 4 | 0 do 4 294 967 295 | vrijeme iz millis() |
float | 4 | oko ±3,4 · 1038, 6 do 7 znamenki | decimalni brojevi: napon, temperatura |
Unsigned znači bez predznaka: takav tip nema negativnih brojeva, pa mu je najveći broj dvostruko veći. Zašto je baš tako, objašnjava stranica Binarni, oktalni i heksadecimalni brojevi.
Kako odabrati tip:
- Za većinu brojeva dovoljan je
int. - Vrijeme iz
millis()uvijek spremaj uunsigned long, jerintnapuni za 33 sekunde (lekcija Dva semafora na križanju). Iz istog razloga u lekciji Tipkala kako treba brojač koji brzo raste dobijeunsigned long. - Za da ili ne koristi
bool, kaoledModeu lekciji Djelilo napona, Arduino i PWM. - Znakove tipkovnice sprema
char, kao u lekciji Mnogo prekidača na malo pinova. floatkoristi samo kad trebaš decimale. Uno nema sklop za računanje s decimalnim brojevima, pa je s njima sporiji, afloatpamti samo 6 do 7 znamenki: 1234,5678 spremi kao otprilike 1234,568.
Nije svaki int jednak
Rasponi u tablici vrijede za 8-bitne mikrokontrolere. Na Unu R4, Gigi i ESP32, koji imaju 32-bitni mikrokontroler, int ima 4 bajta, kao long, i u njega stanu brojevi do 2 147 483 647. Program koji na Unu R3 napuni int tamo zato radi drukčije.
Kad broj mora imati točno zadan broj bitova na svakom mikrokontroleru, koristi tipove kojima je broj bitova u imenu: int16_t (16 bitova s predznakom), uint8_t (8 bitova bez predznaka, isto što i byte) ili uint32_t (32 bita bez predznaka).
Vrijednost koja se ne mijenja: const
Riječ const ispred tipa kaže da se vrijednost ne mijenja dok program radi:
const int ledPin = 9; // pin na koji je spojena LED-ica
const unsigned long SMIRIVANJE = 50; // broj s posebnim značenjem: velikim slovima
Ako program pokuša promijeniti takvu vrijednost, prevoditelj javi grešku. Tako se ne može dogoditi da program slučajno promijeni broj pina. U lekcijama pinove pišemo kao ledPin, a brojeve s posebnim značenjem velikim slovima, kao TREPCE u lekciji o semaforu za pješake i SMIRIVANJE u lekciji o tipkalima.
Gdje živi varijabla
Gdje u programu napišeš varijablu, određuje koliko dugo postoji i tko je smije koristiti:
- Varijabla iznad
setup()(globalna) nastane kad se program pokrene i pamti svoju vrijednost dok program radi. Smije je koristiti svaka funkcija. Ako joj ne zadaš početnu vrijednost, na početku je 0. - Varijabla unutar funkcije, na primjer unutar
loop()(lokalna), nastane iznova pri svakom pozivu i nestane na kraju funkcije. Smije je koristiti samo ta funkcija, a ako je napisana unutar vitičastih zagrada{ }, samo dio programa unutar njih.
Lokalna varijabla bez početne vrijednosti
Lokalna varijabla bez početne vrijednosti nije 0: u njoj je ono što je slučajno ostalo u memoriji. Zato je napiši s početnom vrijednošću, int zbroj = 0;, a ne samo int zbroj;.
Kada koju koristiti, objašnjava okvir Gdje pišemo varijable? u lekciji Dva semafora na križanju.
Računanje s cijelim brojevima
Kad dijeliš dva cijela broja, i rezultat je cijeli broj. Ostatak se odbaci, a ne zaokruži: 7 / 2 je 3, a 9 / 10 je 0. Ostatak dijeljenja daje znak %: 7 % 2 je 1.
Decimalni rezultat dobiješ samo ako je barem jedan broj decimalni: 7 / 2.0 je 3,5. Nije dovoljno rezultat spremiti u float. U retku float x = 7 / 2; Arduino prvo podijeli dva cijela broja, a tek onda 3 spremi u x, pa je x 3,00.
Kad broj prijeđe najveću vrijednost svog tipa, počne ispočetka: byte od 255 nakon + 1 ima 0, a int od 32 767 skoči na −32 768. Najteže se uoči kad se to dogodi usred računa:
unsigned long krivo = 60 * 1000; // 4294961760, a ne 60000
unsigned long dobro = 60 * 1000UL; // 60000
Arduino 60 i 1000 pomnoži kao dva int-a, a 60 000 ne stane u int. Pokvareni rezultat spremi tek na kraju, pa čekanje od jedne minute traje 49 dana. Oznaka UL iza broja kaže da je broj unsigned long, pa se cijeli račun izvede u tom tipu. Prevoditelj javi samo upozorenje integer overflow in expression, i to samo ako su upozorenja uključena: u Arduino IDE-u u File → Preferences → Compiler warnings.
Probaj sam
Ovaj program pokazuje sve zamke s ove stranice. Učitaj ga, otvori serijski monitor i usporedi ispis s komentarima:
void setup() {
Serial.begin(9600);
int a = 7;
int b = 2;
Serial.println(a / b); // 3: cijeli brojevi, ostatak se odbaci
Serial.println(a % b); // 1: ostatak dijeljenja
Serial.println(a / 2.0); // 3.50: 2.0 je decimalni broj
float krivo = a / b; // dijeli cijele brojeve, a tek onda sprema u float...
Serial.println(krivo); // ...pa je 3.00
byte brojac = 255; // najveći byte
brojac = brojac + 1;
Serial.println(brojac); // 0: broj je počeo ispočetka
unsigned long krivoVrijeme = 60 * 1000; // 60 i 1000 su int, a 60000 ne stane u int
unsigned long dobroVrijeme = 60 * 1000UL; // UL: računaj kao unsigned long
Serial.println(krivoVrijeme); // 4294961760
Serial.println(dobroVrijeme); // 60000
char slovo = 'A';
Serial.println(slovo); // A
Serial.println(slovo + 1); // 66: broj sljedećeg znaka
Serial.println(char(slovo + 1)); // B
}
void loop() {
}
Zadnja tri retka pokazuju da je i char zapravo broj: slovo A ima broj 65, B 66 i tako dalje. Serial.println() znak ispiše kao slovo samo dok je tipa char. slovo + 1 je već int, pa ga ispiše kao broj, a char(...) ga pretvori natrag u znak.
Serial.println() decimalni broj ispiše s dvije decimale. Za više decimala dodaj njihov broj: Serial.println(napon, 4);.
Što smo naučili?
- Varijabla ima ime, a u njoj program sprema jedan podatak. Varijabla pamti samo zadnju vrijednost.
- U MakeCodeu varijable su u kategoriji Variables, a vrstu podatka MakeCode prepozna sam. U Arduino programu tip napišemo ispred imena:
int bodovi = 0;. =sprema vrijednost, a==pita jesu li dvije vrijednosti jednake.- Svaki tip ima zadan broj bajtova i raspon. Za većinu brojeva dovoljan je
int, za vrijemeunsigned long, za da ili nebool, afloatsamo kad trebamo decimale. constčuva vrijednost od promjene. Globalna varijabla pamti vrijednost dok program radi, a lokalna nastaje i nestaje s funkcijom.- Dijeljenje dva cijela broja odbaci ostatak, a broj koji prijeđe raspon svog tipa počne ispočetka, i usred računa.
Mali kviz
1. Što je varijabla?
2. U varijablu bodovi spremiš 5, a zatim 8. Što je u njoj?
3. Zašto se varijabla ne smije zvati životi?
4. Koji tip odabrati za vrijeme iz millis()?
unsigned long. int napuni već za 33 sekunde, a u unsigned long stane vrijeme od 49 dana.5. Koliko je 9 / 4 u Arduino programu, a koliko 9 % 4?
9 / 4 je 2, jer se ostatak cijelih brojeva odbaci. 9 % 4 je 1, ostatak dijeljenja.6. Što radi if (stanje = 3)?
stanje spremi 3, a uvjet je uvijek ispunjen. Program je htio pitati if (stanje == 3).7. Zašto unsigned long minuta = 60 * 1000; ne daje 60000?
int, pa ih Arduino pomnoži kao int, a 60 000 ne stane u int. Pokvareni rezultat spremi tek na kraju. Ispravno je 60 * 1000UL.8. Lokalna varijabla int zbroj; napisana je bez početne vrijednosti. Koliko je zbroj?
int zbroj = 0;. Globalna varijabla bez početne vrijednosti bila bi 0.