C++/Muuttujat
Tämä luku kertoo muuttujista. Muuttujat ovat nimiä, joilla käsitellään tiettyä paikkaa muistissa. Muuttujalla on nimen lisäksi tyyppi. Muuttuja on määriteltävä ennen kuin sitä voi käyttää. Määrittely tapahtuu näin:
tyyppi nimi;
Tyyppi kertoo minkä tyyppinen muuttuja on (kokonaisluku, merkkijono, jne.). Nimi on yksinkertaisesti nimi jolla muuttujaa kutsutaan. Nimi voi olla mikä tahansa, kunhan se ei ole varattu sana, ei sisällä erikoismerkkejä kuten ääkkösiä, eikä ala numerolla. Kuten C-kielessä, kirjainkoolla on merkitystä. Näin ollen esimerkiksi auto ei ole sama kuin Auto tai auTo. Näin määritellään int-tyyppinen muuttuja:
int luku;
Jos haluat määritellä monta samantyyppistä muuttujaa kerralla, ne voi erotella pilkuilla:
int luku, toinen, kolmas;
Kun muuttuja on esitelty, siihen voi sijoittaa arvoja. Tämä tapahtuu käyttämällä sijoitusoperaattoria, joka on yksi yhtäläisyysmerkki. Muuttujan arvoksi voi sijoittaa myös toisen muuttujan arvon.
luku = 5; toinen = 2; luku = toinen; // luku on nyt 2
Muuttujia määriteltäessä voidaan se alustaa jollakin tietyllä arvolla:
int luku = 0; int toinen = 5, kolmas = 5;
Merkeissä käytetään puolilainausmerkkejä:
char merkki = 'a';
Merkkijonoissa käytetään lainausmerkkejä:
char* merkkijono = "Merkkijono"; std::string toinen = "Merkkijono2";
Koska C-tyyliset merkkijonot ovat vain char-tyyppisiä taulukoita, ne voidaan määritellä myös seuraavasti:
char merkkijono[] = { 'M', 'e', 'r', 'k', 'k', 'i', 'j', 'o', 'n', 'o', '\0' };
Muuttujatyypit
muokkaaC++ sisältää viisi perustyyppiä muuttujille.
Tyyppi | Kuvaus |
---|---|
bool | totuusarvo |
char | merkki |
int | kokonaisluku |
float | liukuluku |
double | tarkempi liukuluku |
Lisäksi näitä tyyppejä voidaan laajentaa etuliitteillä short, long, signed ja unsigned. Esimerkiksi unsigned int tarkoittaa etumerkitöntä kokonaislukua, joten se voi olla vain positiivinen. Kun listaamme kaikki mahdolliset muuttujatyypit, saamme alla olevan listan. Muuttujien arvoalueet ovat suuntaa antavia. Todellisuudessa arvoalueet ovat järjestelmäriippuvaisia, koska eri arkkitehtuureilla muuttujatyypit vievät eri määrän tavuja. Oikean muuttujan vaatiman tavujen määrän saa selville sizeof()-operaattorilla.
Tyyppi | Kuvaus | Arvoalue |
---|---|---|
bool | totuusarvo | 0…1 (false tai true) |
char | merkki | −128…127 |
unsigned char | etumerkitön merkki | 0…255 |
signed char | etumerkillinen merkki | −128…127 |
int | kokonaisluku | −32768…32767 |
unsigned int | etumerkitön kokonaisluku | 0…65535 |
signed int | etumerkillinen kokonaisluku | −32768…32767 |
short int | lyhyt kokonaisluku | −32768…32767 |
unsigned short int | etumerkitön lyhyt kokonaisluku | 0…65535 |
signed short int | etumerkillinen lyhyt kokonaisluku | −32768…32767 |
long int | suuri kokonaisluku | −2147483648…2147483647 |
unsigned long int | etumerkitön pitkä kokonaisluku | 0…4294967295 |
signed long int | etumerkillinen pitkä kokonaisluku | −2147483648…2147483647 |
float | liukuluku | 1,2E−38…3,4E38 |
double | tarkempi liukuluku | 2,2E−308…1,8E308 |
long double | suuri tarkempi liukuluku | 2,2E−308…1,8E308 |
long long | erittäin pitkä kokonaisluku | −9223372036854775808…9223372036854775807 |
unsigned long long | etumerkitön erittäin pitkä kokonaisluku | 0…18446744073709551615 |
Lyhyet ja pitkät kokonaisluvut short int ja long int voidaan vaihtoehtoisesti kirjoittaa myös short ja long.
Vertailu
muokkaaC++ sisältää kuusi operaattoria joiden avulla muuttujia ja muita arvoja voi vertailla toisiinsa.
Operaattori | Kuvaus |
---|---|
== | yhtäläisyys |
!= | eri suuri kuin |
< | pienempi kuin |
<= | pienempi tai yhtä suuri kuin |
> | suurempi kuin |
>= | suurempi tai yhtä suuri kuin |
Nämä operaattorit palauttavat totuusarvon joka kertoo, onko vertailun tulos tosi vai epätosi. Jos vertailu pitää paikkansa, palautetaan true (1, tosi), ja false (0, epätosi), jos vertailu ei pidä paikkaansa. Huomaa, että operaattori joka vertaa yhtäsuuruutta on == eikä =, joka on sijoitusoperaattori.
(4 == 4) // tosi (2 == 4) // epätosi (2 < 4) // tosi // // Muuttujia voi vertailla samalla tavalla // int muuttuja, toinen; muuttuja = 7; toinen = 5; (muuttuja == toinen) // epätosi (muuttuja >= toinen) // tosi // // Seuraava vertailu olisi virheellinen, sillä yhtäläisyysmerkkiä // käytetään sijoitusoperaattorina, ei vertailussa. // (muuttuja = 4) // VIRHE!
Tyyppimuunnokset
muokkaaTyyppimuunnos tarkoittaa muuttujan tyypin muuttamista joksikin toiseksi. Koska C++ on staattisesti tyypitetty kieli, et voi käyttää samaa muuttujatyyppiä kaikissa tilanteissa, vaan joudut tekemään tyyppimuunnoksia. Jotkut funktiot saattavat vaatia parametreikseen int-tyyppisen muuttujan, jolloin saatat joutua muuntamaan esimerkiksi float-muuttujan int-tyypiksi.
Tyyppimuunnokset voivat aiheuttaa tarkkuuden menetystä. Jos muunnat esimerkiksi double-muuttujan tyypiksi int, menetät kaikki desimaalit, koska int pystyy sisältämään vain kokonaislukuja.
C-tyyliset tyyppimuunnokset
muokkaaVoit tehdä C-tyylisen tyyppimuunnoksen laittamalla muuttujan eteen sulkuihin tyypin, johon haluat muuntaa:
tyyppi muuttuja = (tyyppi)muutettava;
Alla on esimerkkejä erilaisista tyyppimuunnoksista.
int kokonaisluku = 5; float liukuluku = 1.6; char merkki = 'c'; int toinenluku = (int)merkki; liukuluku = (float)kokonaisluku; kokonaisluku = (int)liukuluku;
C++-tyyliset tyyppimuunnokset
muokkaaC++ tukee C-tyylisiä tyyppimuunnoksia, mutta sisältää muitakin tapoja muuntaa muuttujan tyyppi. Eräs tapa on funktiokutsua muistuttava tyyppimuunnos. Tällainen muunnos vastaa C-tyylistä tyyppimuunnosta.
tyyppi(muutettava)
Alla esimerkkejä tällaisista tyyppimuunnoksista:
int kokonaisluku = 5; float liukuluku = 1.6; char merkki = 'c'; int toinenluku = int(merkki); liukuluku = float(kokonaisluku + toinenluku); kokonaisluku = int(merkki) + toinenluku;
Joissakin tapauksissa tällaiset tyyppimuunnokset voivat luoda virhetilanteita, eikä niiden käyttöä yleensä suositella. ISO-standardin mukainen C++ määrittelee muitakin tyyppimuunnoksia, jotka ovat turvallisempia kuin vanhat C-tyyliset muunnokset.
static_cast
muokkaaStaattinen tyyppimuunnos static_cast-operaattorilla on C++:n normaali tyyppimuunnos. Se tekee puhtaan tyyppimuunnoksen kääntämisvaiheessa, ja toimii melkein samalla tavalla kuin C-tyylinen tyyppimuunnos. Tällaista muunnosta käytetään sellaisten tyyppien kanssa, joille voidaan tehdä myös päinvastainen muunnos.
static_cast<tyyppi>(muutettava)
Esimerkkejä tällaisista tyyppimuunnoksista:
double a = 3.0; int b = static_cast<int>(a); // b on nyt 3 int c = static_cast<int>(7.5); // desimaalit häviävät
Toisin kuin C-tyylinen muunnos, static_cast ei varoita vaikka tietotyypin muuntamisessa tapahtuisi tarkkuuden menetystä. Näin käy yllä olevassa esimerkissä, jossa desimaaliluku 7.5 muunnetaan kokonaisluvuksi.
Jos operaattorilla muunnetaan osoitinta, osoitin muunnetaan halutun tyyppiseksi osoittimeksi. Osoittimien kanssa kannattaa kuitenkin olla tarkkana, sillä static_cast ei varmista että osoittimen tyyppi on yhteensopiva sen tyypin kanssa johon muunnetaan. static_cast ei kuitenkaan salli esimerkiksi const-arvon muuntamista muokattavaksi.
dynamic_cast
muokkaadynamic_cast on turvallisempi vaihtoehto static_cast-operaattorille, koska se tekee ajonaikaisen tyyppitarkistuksen, varmistaen että tyyppimuunnos on laillinen. Tästä syystä se on kuitenkin yleensä myös hitaampi. Operaattoria käytetään osoittimien ja viittausten kanssa.
dynamic_cast<tyyppi>(muutettava)
Dynaamista muunnosta kannattaa käyttää kun ei olla varmoja minkä tyyppinen muutettava arvo on. Jos operaattorilla yritetään muuntaa osoitin jonka tyyppi ei ole yhteensopiva, dynamic_cast palauttaa nollaosoittimen. Jos palautettu arvo on siis NULL, tyyppimuunnos ei onnistunut eikä muunnettua arvoa näin ollen voi käyttää. Samassa tilanteessa static_cast ei huomaisi virhettä.
Jos operaattorilla yritetään muuntaa viittausta ja se epäonnistuu, dynamic_cast aiheuttaa poikkeuksen std::bad_cast.
const_cast
muokkaaconst_cast-operaattorilla voi poistaa tai lisätä vakion const- tai volatile-määreen.
const_cast<tyyppi>(muutettava)
Tämä operaattori on hyödyllinen erityisesti silloin, kun jokin funktio vaatii argumentikseen muuttujan, mutta sille annetaan vakio. Funktio voisi olla esimerkiksi seuraavanlainen:
int tee_jotakin(int &argumentti);
Saattaisit käyttää funktiota toisessa funktiossa esimerkiksi näin:
void kayta_funktiota(const int &luku) { int arvo = tee_jotakin(luku); }
Tässä tapauksessa kääntäjä ilmoittaa virheestä, koska funktio tee_jotakin saattaisi muuttaa luku-vakion arvoa. Tämä ei tietenkään ole mahdollista, sillä vakioiden arvoja ei voi muuttaa. Ongelman voi korjata helposti poistamalla muuttujan vakioisuuden käyttämällä const_cast-operaattoria ennen kuin arvo syötetään funktiolle.
void kayta_funktiota(const int &luku) { int arvo = tee_jotakin(const_cast<int&>(luku)); }
reinterpret_cast
muokkaareinterpret_cast<tyyppi>(muutettava)
Vakiot
muokkaaVakiot ovat muuttujia, joiden arvoa ei voi muuttaa. C++:ssa vakioita määritellään avainsanalla const (engl. constant = pysyvä). Vakioita käytetään silloin, kun arvoa kirjoitetaan useita kertoja, mutta sitä ei tarvitse ikinä muuttaa. Muuttuja määritellään vakioksi alustuksen yhteydessä.
const tyyppi nimi = arvo;
Esimerkkejä vakioiden määrittelyistä:
const int luku = 32; const float liukuluku = 2.47; const std::string merkkijono = "Päivää.";
Esimerkiksi yllä olevassa koodissa luku-vakion arvoksi on määritelty 32. Tätä arvoa ei voi enää muuttaa. Jos ohjelmoija yrittää muuttaa arvoa, kääntäjä ilmoittaa virheestä.