58127-1 C-ohjelmointi : 9 Muita C-kielen piirteitä
9 Muita C-kielen piirteitä
Tässä osuudessa käsitellään luetellut tyypit, esikääntäjäkomennot, esikääntäjävakiot, binääriaritmetiikka (bittioperaatiot) ja ehdollinen lause lyhyesti. Jos haluat tietää lisää, niin katso kurssikirjasta vastaavia kohtia.9.1 Luetellut tyypit (enumerations)
Luetellut tyypit ovat kokonaislukuvakioita joille on annettu toinen nimi. Syntyy uusi tyyppi jolla on vain muutama sallittu arvo. Kätevä jos tarvitsee käsitellä "maagisia" lukuja. Enumeraation elementit sisältävät arvoja nollasta ylöspäin. Yleisesti:
enum tyyppi { elementti1, ..., elementtiN };Esimerkkejä:
enum Color { Red, Green, Blue, Black, White }; enum Color Vari1; enum Color Vari2 = Green; enum Color Sateenkaari[5];Oletuksena ensimmäisen elementin arvo on 0, toisen 1 jne. Enumeraation elementeille voi myös antaa omia arvoja, esim.:
enum Autoja { Opel = 10, BMW, Mercedes = 20, Ford }; enum t_boolean { false = 0, true = 1 }; /* luodaan enumeraatio kahdella arvolla */ typedef enum t_boolean boolean; /* annetaan sille kätevämpi nimi */ boolean Lippu = true;Enumeraatiomuuttuja voi ainoastaan sisältää enumeraatiossa esitellyt "arvot". Ainoat sallitut operaatiot ovat kopiointi ja vertaus.
9.2 Esikääntäjäkomennot
Esikääntäjä on ohjelma joka käsittelee jokaisen käännettävän tiedoston ennen varsinaista käännöstä. Esikääntäjälle voi antaa komentoja jotka alkavat merkillä #. Päätehtävä on kuitenkin otsikkotiedostojen liittäminen käännettäviin ohjelmiin. Tehdään tutusti komennolla #include, mutta ilman kaksoispistettä lopussa. Tiedostonimi voidaan antaa muodossa <nimi> tai "nimi". Viimeksi mainittu viittaa otsikkotiedostoihin samassa hakemistossa.Esikääntäjävakioita voi määritellä esikääntäjän avulla. Voidaan siirtää "maagisia" lukuja vakioiksi. Tehdään komennolla #define. Yleisesti:
#define vakionimi arvo, missä vakionimi on vakio jota voidaan käyttää ohjelmassa. Usein käytetään ISOJA KIRJAIMIA kun nimetään esikääntäjävakioita. Puolipistettä ei tarvita. Esikääntäjä korvaa kaikki vakiot niiden arvoilla ennen käännöstä. Esimerkkejä:
#define VIESTI "Hello World!" #define MIN_ARVO 0 #define MaxArvo 100 #define Pii 3.14159265358979323846Mikä tahansa nimi voidaan korvata toisella. Esimerkiksi:
#define forever for(;;) /* ikuinen silmukka */
On mahdollista myös määritellä makroja, joilla on parametrejä siten, että korvattava teksti on erilainen jokaisella makron kutsukerralla. Esimerkkinä makro max:
#define max(A,B) ((A) > (B) ? (A) : (B)) /* Nyt siis seuraava lause on mahdollista */ x = max(p+q,r+s); /* Tämä rivi siis korvautuu esikäännöksessä rivillä */ x = ((p+q) > (r+s) ? (p+q) : (r+s));
Joten sulkujen kanssa täytyy olla huolellinen. Esimerkiksi seuraava makro on virheellinen:
#define square(x) x * x /* Tuo määritys on väärin esimerkiksi seuraavalla kutsulla */ m = square(z+1); /* Sillä kutsu laajenee muotoon */ m = z+1 * z + 1; /* Joten oikea muoto on luonnollisesti */ #define square (x) ((x) * (x))
9.3 Bittioperaatiot
Bittioperaatioissa käytetään lukujen binääristä muotoa ja manipuloidaan sitä. Tähän käyttöön on shiftausoperaattorit << ja >>. "shiftaavat" binäärimuodon vasemmalle tai oikealle. Käytännössä kertominen tai jako "multippelilla" luvusta 2. Esimerkiksi
10 << 2 == 40 15 << 3 == 90 10 >> 1 == 5 10 >> 2 == 2Tämän lisäksi on olemassa seuraavat operaattorit:
- binääri and operaattorilla &
- binääri or operaattorilla |
- binääri exclusive or operaattorilla ^
- binääri not operaattorilla ~
9.4 Operaattori ?
Operaattori ? toimii periaatteessa kuin if-lause. Yleinen muoto:ehto ? lause1 : lause2;Huomaa, että puolipiste (;) on ainoastaan lause2:n jälkeen. Jos ehto on tosi suoritetaan lause1, muutoin lause2. Lisäksi lause1 ja lause2 voivat myös palauttaa arvon. Esimerkkejä:
/* anna luvuille Luku1 ja Luku2 arvoja */ int Luku1 = ...; int Luku2 = ...; int Pienempi = Luku1 < Luku2 ? Luku1 : Luku2; /* esimerkki jossa ei palauteta arvoa: */ int Vuosi = 2000; Vuosi == 2000 ? printf ("Vuosi on 2000\n" ) : printf ("Vuosi ei on 2000\n" ); /* esimerkki yllä toisella tavalla */ int Vuosi = 2000; printf ( "Vuosi %s 2000\n", Vuosi == 2000 ? "on" : "ei ole" );
Jan Lindström (Jan.Lindstrom@cs.Helsinki.FI)