C-ohjelmointi Luento 5: Osoittimet

Samankaltaiset tiedostot
C-ohjelmointi Luento 5: Osoittimet Tiina Niklander

Sisältö. C-ohjelmointi Luento 5: Osoittimet. Keko (heap) Pino (stack) Muistinhallinta Java vs C. Prosessin rakenne

C-ohjelmointi: Osoittimet

Rakenne. C-ohjelmointi: Tietorakenteita ja tyyppejä. Tyyppimuunnoksia aritmeettisten tyyppien välillä. Tyyppimuunnokset. & (bitti and) Bittioperaatiot

Lyhyt kertaus osoittimista

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Rakenteiset tietotyypit Moniulotteiset taulukot

Dynaaminen muisti. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät 2017.

Osoitin ja viittaus C++:ssa

Dynaaminen muisti Rakenteiset tietotyypit

Tietueet. Tietueiden määrittely

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

C-ohjelmointi, syksy 2006: Funktiot

TITO. ltö. C-ohjelmointi, syksy 2006: Funktiot. Aliohjelmaesimerkki. Esimerkki: potenssiin korotus. Luento 4, ti

C-ohjelmointi, syksy 2006

C-ohjelmointi, syksy Yksiulotteiset taulukot Moniulotteiset taulukot Dynaamiset taulukot. Binääritiedostot. Luento

1. Mitä seuraava ohjelma tulostaa? Vastaukseksi riittää yksi rivi joka esittää tulosteen. (6 p)

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Luennon sisältö. Taulukot (arrays) (Müldnerin kirjan luku 10) Yksiulotteiset taulukot. Mikä taulukko on? Taulukko-osoitin. tavallinen osoitin

Osoittimet ja taulukot

Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö C-ohjelmassa

Tietorakenteet ja algoritmit

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Jakso 4 Aliohjelmien toteutus

Jakso 4 Aliohjelmien toteutus

Luento 4 Aliohjelmien toteutus

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

C-kurssi syksy ltö. Luennon sisält. Luento 2: tyypit, rakenteet, makrot Tyypit. signed, unsigned short,, long Vakiot const Rakenteet

Luennon sisält. ltö. C-kurssi syksy ääreet: int ja char. Yksinkertaiset tyypit. Kokonaisluvut. Merkit

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

7. Oliot ja viitteet 7.1

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Ohjelmointi 1 Taulukot ja merkkijonot

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Luennon sisältö Tyypit int, char, float, double signed, unsigned short, long Vakiot const Rakenteet if, for, while, switch, do-while Syöttö ja tulostu

Loppukurssin järjestelyt

Loppukurssin järjestelyt C:n edistyneet piirteet

Moduli 4: Moniulotteiset taulukot & Bittioperaatiot

Java-kielen perusteet

Merkkijono määritellään kuten muutkin taulukot, mutta tilaa on varattava yksi ylimääräinen paikka lopetusmerkille:

Osoittimet ja taulukot

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Jakso 4 Aliohjelmien toteutus

C-kurssi kevät t Luento 2: tyypit, rakenteet, makrot

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

Moduli 2: Osoittimet ja taulukot. Joel Huttunen

Luennon sisältö. C-kurssi kevät Tasokokeen kohta 1: Taulukon järjestäminen. Tasokokeen kohta 2. Tasokokeen kohta 2. Tasokokeen kohta 3

C-kurssi kevät Luennon sisältö

Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat:

Sisältö. 22. Taulukot. Yleistä. Yleistä

Java-kielen perusteet

Taulukot. Jukka Harju, Jukka Juslin

Harjoitustyö: virtuaalikone

1. Esittelyt ja vakiot 1.1 Esittelyt (declarations) Ennen nimen, tunnuksen (identifier) käyttöä se on

Luento 4 Aliohjelmien toteutus

Luento 4 Aliohjelmien toteutus

Tietorakenteet ja algoritmit

Jakso 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

Luento 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

Ohjeet. AS C-ohjelmoinnin peruskurssi Aalto-yliopiston sahkotekniikan korkeakoulu Tentti , Raimo Nikkila

Tietorakenteet ja algoritmit

Sisältö. 2. Taulukot. Yleistä. Yleistä

ltö C-ohjelmointi Luento 6: tietueet ja joukot Tietueet (struct( struct) Lueteltu tyyppi (enum( enum) Union Linkitetty lista

C-ohjelmointi: Funktiot. Luento: viikko 2

Harjoitus 4 (viikko 47)

C-ohjelmointi, syksy 2008: Funktiot

Tietorakenteet ja algoritmit

Moduli 5: Kehittyneitä piirteitä

TIETORAKENTEET JA ALGORITMIT

11/20: Konepelti auki

Tieto- ja tallennusrakenteet

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

ITKP102 Ohjelmointi 1 (6 op)

C++11 lambdat: [](){} Matti Rintala

TITO. C-ohjelmointi, syksy 2008: Funktiot. ltö. Aliohjelmaesimerkki. Esimerkki: potenssiin korotus. Luento 4, pe

Tietorakenteet ja algoritmit

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Tietotyypit ja operaattorit

Ohjelmoinnin perusteet Y Python

C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. Operaatioiden suoritusjärjestys

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Nimike Määrä YksH/EI-ALV Ale% ALV Summa

C-ohjelmointi, kevät Merkkijonot Komentoriviparametrit. Luento

C-ohjelmointi, syksy Merkkijonot Komentoriviparametrit. Luento C-ohjelmointi Syksy

Merkkijonot Komentoriviparametrit

Ohjelmoinnin perusteet Y Python

Merkkijonot Komentoriviparametrit

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

815338A Ohjelmointikielten periaatteet

5.6. C-kielen perusteet, osa 6/8, Taulukko , pva, kuvat jma

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

Geneeriset luokat. C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet. Geneerisen luokan käyttö.

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

C-ohjelmointi, kevät 2006: Funktiot

TITO. Sisältö. C-ohjelmointi, kevät 2006: Funktiot. Aliohjelmaesimerkki. Yleistä. Parametrit. Esimerkki: potenssiin korotus

Transkriptio:

C-ohjelmointi Luento 5: Osoittimet 19.9.2006 Sisält ltö umuistin rakenteesta uoperaatiot ja void-tyyppi umuistinhallinta varaus, vapautus uosoitinaritmetiikka ja muistilohkon käsittely uosoittimet ja funktiot uosoitinlohko umerkkijonojen kopiointi (jos ehditää ään) 1

Muistinhallinta Java vs u Luokka on viittaustyypin määritelmä ja olio on viittaustyypin ilmentymä u Muistinhallinta on implisiittistä.. Java suoritusympärist ristö varaa muistia uusille olioille aina oliota luotaessa u Roskienkeruu vapauttaa muistia eli poistaa muistista ne oliot, joihin ei enää ole viittauksia u Mikä sitten on olioviite???? (No se on oikeastaan osoitin) C u Ei luokkia, mutta kuitenkin tietorakenteita ja osoittimia u Eksplisiittinen muistinhallinta. Ohjelman on varattava muistia uusille tietorakenteille. u Eksplisiittinen vapautus. Ohjelman on vapautettava tarpeeton muisti. u Osoittimet ovat oikeastaan vain viittauksia muistissa oleviin tietoalkioihin Prosessin rakenne PCB Ohjelma-alue Data-alue (keko) Pino alueen lopussa Suhteellisia viittauksia prosessin omalla muistialueella 2

Pino (stack) push top pop u Implisiittinen käyttö (paikalliset muuttujat ja funktion param.) u Hyöty ty: Muistia ei tarvitse varata tai vapauttaa itse. u Haitta: Pinon alkioita voi käyttää vain sen hetken kun ne ovat pinossa.. (Täst( stä voi seurata virheitä, jos näihin viitataan osoittimilla.) u Roikkuva viite (dangling reference) Osoitin, joka vieläkin viittaa jo vapautettuun muistialueeseen Keko (heap) u Eksplisiittinen käyttö u Ohjelmoija vastaa muistinhallinnasta C:ssä u Muisti voi pirstoutua (fragmentatoitua) free u Sopimaton tai huolimaton käyttö voi johtaa muistivuotoon u Muisti on resurssi (siinä kuin tiedostotkin) ja sitä pitää hallita ihan yhtälailla 3

Osoittimien määrittely ja viittaukset u Osoittimen voi määritellä mille tahansa tyypille int *p; Osoitin kokonaislukuun char *q; Osoitin merkiin (merkkiosoitin) double **w; Osoitin reaalilukuosoittimeen u Tässä siis p osoittaa muistialueeseen, jonka koko on sizeof(int) q osoittaa muistialueeseen, jonka koko on sizeof(char) w osoittaa muistialueeseen, jonka koko on sizeof(double*) u Tai tyyppimää äärittelyllä: typedef int* * Pint; Pint p1, p2; /*p1 ja p2 ovat osoittimia int-tyyppiin tyyppiin */ u p = &c u c = *p u c = **r u p = q u p+i u p-i u p-q Operaatiot osoitteen otto osoitetun muuttujan arvo - - (Nyt vain kaksi osoitinta peräkk kkäin) sijoitus, kun samantyyppiset osoittimet p osoitin muistialueelle, i sopivan kokoinen kok.luku saman muistialueen osoittimia ja q<p u *ip++ osoittimen arvo kasvaa yhdellä u (*ip ip)++ osoitetun muuttujan arvo kasvaa yhdellä! 4

Operaatiot (jatkuu) u p < q u p == q p ja q saman muistialueen osoittimia u Osoitinaritmetiikka toimii viitattavan tyypin koosta riippumatta: pa+1 viittaa seuraavaan samantyyppiseen alkioon. (tai pa[i]) *(pa+i pa+i) on kyseisen alkion arvo u Osoittimen arvo NULL ei osoita mihinkää ään u NULL-arvon voi sijoittaa mille tahansa osoitinmuuttujalle tyypistä riippumatta. Osoittimet ja sijoitus int i; int *iptr = &i; int j = 3; int *jptr = &j; u Entäpä iptr i? *jptr = *iptr* iptr; i = 4; *jptr = i; iptr = j; jptr j 3 5

Geneeriset osoittimet (void *p) u void *p määrittelee geneerisen, tyypittömän osoittimen p. u Osoitinta voidaan tyyppimuunnoksen *(T*)p avulla käyttää käsiteltäessä tyypin T muuttujaa void *p = NULL; int i = 2; int *ip = &i; HUOM: Tyyppimuunnos! p = ip; printf("%d", ", *p); /* VÄÄV ÄÄRIN?*/ printf("%d", ", *((int int*)p ) ); Osoittimet jaconst -määre uconst int *p; p:n arvo on osoitin kokonaislukuvakioon p voi muuttua, mutta *p ei uint *const p; vakio-osoitin osoitin kokonaislukuun *p p ei voi muuttua, mutta *p voi uconst int *const p; Vakio-osoitin osoitin kokonaislukuvakioon. 6

Sisält ltö umuistin rakenteesta uoperaatiot ja void-tyyppi umuistinhallinta varaus, vapautus uosoitinaritmetiikka ja muistilohkon käsittely uosoittimet ja funktiot uosoitinlohko umerkkijonojen kopiointi (jos ehditää ään) malloc, calloc ja free void * on yleinen osoitin, joka voi osoittaa millaiseen rakenteeseen tahansa. u void *malloc (size_t size); varaa muistia size tavua ja palauttaa osoittimen varatun muistin alkuun. malloc palauttaa NULL, jos muistin varaus ei onnistu. u void *calloc (size_t nobj, size_t size); * calloc on kuten malloc,, mutta varattavan muistin mää äärä on nobj*size tavua ja muisti nollataan. u void *realloc (void *p, size_t size); * realloc muuttaa parametrina annetun osoittimen p osoittaman varatun muistialueen kokoa. u void free (void *p); * free vapauttaa dynaamisesti varatun muistin takaisin käyttk yttöjärjestelmälle. lle. 7

Paluuarvon tarkistus! u Hyvää ään n ohjelmointitapaan kuuluu, että aina tarkistetaan funktion palauttama arvo ja toimitaan sen mukaan. u Erityisen tärket rkeää tämä on mm. muistin varauksen yhteydessä. void *malloc(size_t* requestedsize); void *calloc(size_t* requestedcount, size_t requestedsize); T *p; if ((p=malloc(n malloc(n*sizeof(t))) == NULL) error; if ((p=calloc(n calloc(n, sizeof(t))) == NULL) error; Dynaaminen muistinvaraus: n kokonaislukua int* * p; if((p = malloc(n*sizeof(int sizeof(int))) == NULL) error /* tai makrolla */ #define MALLOC(p,, type, n) \ ((p) = malloc((n)* )*sizeof(type))) == NULL) /* makron käyttö */ if MALLOC(p, int,, n) {error 8

malloc u Käytä aina absoluuttisen numeerisen arvon sijasta alkion kokona sizeof(type) varausfunktion kutsussa. u Esimerkiksi malloc(sizeof(int)) on parempi kuin malloc(2) u Tyypin koko voi vaihtua ympärist ristöstä toiseen Muistin vapauttaminen ueksplisiittisesti keosta varattu muisti pitää myös vapauttaa eksplisiittisesti, kun sitä ei enää tarvita. int *p; if(malloc(p, int, 1)) exit(exit_failure); *p = 12;... free(p); p = NULL; /* Älä enää käytä osoitinta *p */ Varaus Vapautus 9

Muistinhallinta u Älä sekoita implisiittisesti (pinosta) ja eksplisiittisesti (keosta) varattua muistia. int i; int *p; &i = malloc(sizeof(int)); /*VÄÄ ÄÄRIN*/ u Vapauta ainoastaan aiemmin eksplisiittisesti malloc tai calloc kutsuilla varattua muistia. Vapauta vain kerran! p = &i; free(p); /* VÄÄV ÄÄRIN */ Muistinhallinta u Osoittimen arvon sijoittaminen q = p EI kopioi osoitettua muistia. Sijoituksen jälkeen sekä p että q osoittamaan SAMAAN muistialueeseen. u Näin ollen kutsu free(p) vapauttaa myös q:n osoittaman muistialueen. Älä siis käytä q:ta tai vapauta samaan muistialuetta toistamiseen. p q free(p) p q? 10

Osoitin muistilohkoon u Osoittimen voidaan katsoa osoittavan yhtenäisen muistialueen (muistilohkon) ensimmäiseen iseen alkioon u Lohkon sisäll llä voidaan tiettyyn alkioon i viitata lisää äämällä tuo i osoitinmuuttujan arvoon: pa+i u Alkion arvo saadaan lausekkeella *(pa+i)tai pa[i] u Älä kadota dynaamisesti varatun lohkon alkua. Pidä siis ainakin yksi osoitin koko ajan lohkon ensimmäisess isessä alkiossa u Lohkon läpikl pikäynti for (pi( = p; pi < p+size; pi++) { Viittaus tiettyyn alkioon u Kokonaisluvun lisää ääminen siirtää osoitinta kokonaisen osoitetun alkion verran eteenpäin #define SIZE 3 double *p; if(malloc(p,, double, SIZE)) exit(exit_failure); *p = 1; *(p + 1) = 2; /* tai p[1]*/ *(p + 2) = 3; Vähennyslasku Vastaavasti! 1 2 3 p p+1 p +2 11

Osoittimien välinen v erotus uosoittimen vähentv hentäminen toisesta q p tuottaa tulokseksi osoittimien etäisyyden muistialueen alkioina. HUOM: oltava q>=p int x; p p+1 q x = q-p; x = (p+1) p; Esimerkki: muistilohkon läpikäynti #define SIZE 15 double *p, *pi; if(malloc(p,, double, SIZE)) exit(exit_failure); /* alkioiden sijoittelu muistilohkoon */ for(i = 0, pi = p, sum = 0; i < SIZE; i++, pi++) sum = sum + (*pi); for(pi = p, product = 1; pi < p+size; ; pi++) product *= *pi; /* tulosta alkiot lopusta alkaen */ for(pi = p+size-1; pi >= p; pi-- --) printf("%f\n", ", *pi); 12

Muistilohkon kopiointi alkio kerrallaan u Kopioidaan osoittimen p osoittama alue osoittimen q osoittamalle alueelle. Alueiden koko on SIZE alkiota /* p:lle on jo aiemmin varattu tila ja asetettu arvot muistilohkon alkioille */ double *pi, *qi* qi; if(malloc(q,, double, SIZE)) exit(exit_failure); for(qi = q, pi = p; qi < q+size; qi++, pi++) *qi = *pi; Muistilohkon kopiointi: memcpy ja memmove u Otsikkotiedostossa string.h on joidenkin muistilohkoja käsittelevien standardifunktioiden määm äärittelyjä. u Esimerkiksi void *memcpy(void *dest, const void *src, size_t len); u Kopioi len-mittaisen muistilohkon osoitteesta src alkaen lohkoon, joka alkaa osoitteesta dest u Jos lohkot ovat osittain pääp äällekkäin on käytettk ytettävä funktiota void *memmove(void* *dest,, const void *src* src, size_t len); 13

Sisält ltö umuistin rakenteesta uoperaatiot ja void-tyyppi umuistinhallinta varaus, vapautus uosoitinaritmetiikka ja muistilohkon käsittely uosoittimet ja funktiot uosoitinlohko umerkkijonojen kopiointi (jos ehditää ään) Osoittimet ja funktiot ukaikki funktioiden tekemät dynaamiset muistinvaraukset täytyy dokumentoida huolellisesti ukutsujan täytyy tietää kenen vastuulla muistin vapauttaminen myöhemmin on 14

Osoitin paluuarvona u Funktio varaa muistialueen ja palauttaa arvonaan osoittimen tähän alueeseen u Kutsuja voi käyttää aluetta ja sen vapauttaminen jää kutsujan vastuulle!! /* funktio: getblock *gets a block of memory *to store int values */ int* getblock (size_t size) { return malloc (size*sizeof(int sizeof(int)); int *p; if((p = getblock(10)) == NULL) error /* vapautus joskus myöhemmin */ free(p); p = NULL; Osoitinmuuttuja viiteparametrina u Jos funktion täytyy t muuttaa osoitinmuuttujan arvoa, on funktiolle välitettv litettävä osoitinmuuttujan osoite int getblockref(int **p, unsigned n) { if((*p = (int( int*) *)malloc(n*sizeof(int))) == NULL) return 0; return 1; int *q; if(getblockref( ( &q, 10) == 1) success Osoittimen osoite (osoitinmuuttujan oma osoite) p q *p 230 (&q) 12345? 12222 12998 15

Muistilohko parametrina u Funktiolle parametrina lohkon alun osoite sekä lohkon alkioiden lukumäärä void *funktio(void *ptr, size_t len); u Varattu muistilohko on vain varattu muistilohko Se ei sisällä tietoa koosta tai alkioiden tyypistä Kokotieto täytyy säilyttää ja välittää erikseen Myös tietotyypistä on erillään lohkosta itsestään Etsintäfunktio search /* Search a block of double values */ int search( const double *block, size_t size, double value) { double *p; if(block == NULL) return 0; Alkioiden lkm Osoitin viiteparametrina, jota ei saa muuttaa! for (p = block; p < block+size; p++) if(*p == value) return 1; Lohkon läpikäynti return 0; 16

Yleistetää ään etsintäfunktio search u C ei salli polymorfismia, mutta voimme simuloida sitä käyttämällä geneerisiä osoittimia (i.e. void*). u Funktion esittelyssä voi määritellä, että paluuarvo ja parametrit ovatkin määräämätöntä tyyppiä void u Tällöin tosin on kerrottava myös alkioiden koko ja niiden käsittelyyn käytettävä rutiini Etsittävän lohkon alku int searchgen ( const void *block, size_t size, void *value, size_t elsize int (*compare)(const void *, const void *)); alkioiden lkm ja etsittävä arvo Alkion koko Funktio alkioiden vertailuun Funktion kutsujan toimenpiteet u Funktion kutsujan täytyy määritellä vertailufunktio,, jota voidaan kutsua etsintäfunktiosta (ns. Call back -rutiini) u Tyyppien kanssa määrittely voisi olla: int comp(const double *x, const double *y) { return *x == *y; u Tyypittömien parametrien avulla funktio täytyykin määritellä seuraavasti: int comp(const void *x, const void *y) { return *(double*)x == *(double*)y; 17

geneerisen etsinnän käyttö /* Application of a generic search */ #define SIZE 10 double *b; double v = 123.6; int i; int main (void) { if(malloc(b, double, SIZE)) exit(exit_failure); for(i = 0; i < SIZE; i++) /* initialize */ if(scanf("%lf", &b[i])!= 1) { free(b); exit(exit_failure); printf("%f was %s one of the values\n", v, searchgen(b, SIZE, &v, sizeof(double), comp) == 1? "" : "not"); return 0; /* tai exit(exit_success); */ Geneerisen funktion search toteutus #define VOID(targ,size) ((void *) (((char *)(targ)) + \ (size))) int searchgen(const void *block, size_t size, void *value, size_t elsize, int (*compare)(const void *, const void *)) { void *p; if(block == NULL) return 0; for(p = (void*)block; p< VOID(block,size*elsize); p = VOID(p,elsize)) if(compare(p, value)) return 1; return 0; HUOM: Osoittimen siirrossa on nyt otettava myös alkion koko huomioon! 18

Sisält ltö umuistin rakenteesta uoperaatiot ja void-tyyppi umuistinhallinta varaus, vapautus uosoitinaritmetiikka ja muistilohkon käsittely uosoittimet ja funktiot uosoitinlohko umerkkijonojen kopiointi (jos ehditää ään) Osoitin lohkoon, jossa osoittimia p 2.1 3.1 4.1 u Lohko, jossa on kolme osoitinta double-tyyppisiin alkioihin u Viittaamineen alkioon asti vaatii kaksi viittauksenpurkua **p 19

kk joulu tammi huhti helmi maalis touko syys loka marras kesä elo Osoitinlohko, jonka alkiot merkkijono-osoittimia osoittimia huono heinä u Tällaista rakennetta käytetk ytetään komentoriviparametrien käsittelyssä (muuttuja argv). u Tässä esimerkkinä funktio, joka palauttaa arvonaan osoittimen kuukauden numeroa vastaavaan nimeen. char *kk_nimi(int k) { static char *kk[] = { huono, tammi, helmi, maalis, huhti, touko, kesä, heinä, elo, syys, loka, marras, joulu ; return ( (k<1 k > 12)? kk[0] : kk[k] ); Osoitinlohkon käyttö dynaaminen muistinvaraus lohkolle ja viitattaville alkioille (tai uusille lohkoille) Varaus itse osoitinlohkolle double **block; #define SIZE 3 if((block=calloc(size calloc(size, sizeof(double*)))==null) error; for(i = 0; i < SIZE; i++) if((block[i]=calloc(1, sizeof(double)))==null) error; *(*block) = 2.1; block[0][0] = 2.1; Varaus yhdelle alkiolle kerrallaan 20

Osoitinlohkon käyttö viittaaminen alkioihin ja vapautus u Lohkon viittaamien alkioiden alustaminen for(i = 0; i < SIZE; i++) block[i][0] = 2.1 + i; u Muistinvapauttaminen: viitatut alkiot ja osoitinlohko for(i = 0; i < SIZE; i++) free(block[i]); free(block); block = NULL; Ensin alkiot Ja sitten lohko Esimerkki: merkkijonon kopiointi (merkkijonon lopussa on merkki \0 ) #include <stdio.h> void kopioi( char *s, char *t) { int i =0; while ( (s[i] = t[i])!= \0 ) i++; Merkkijono parametrina. Oikeasti osoittimia muistilohkojen alkuihin. int main (void) { char taalta [] = Tämä kopioidaan., tanne[50]; kopioi ( tanne, taalta); printf( %s\n, tanne); return 0; Viitataan merkkeihin taulukkomaisesti yksi kerrallaan 21

Esimerkki: merkkijonon kopiointi muita tapoja kirjoittaa viittaus Versio 1: Versio 2: void kopioi( char *s, char *t) { while ( (*s = *t)!= \0 ) { s++; t++; void kopioi( char *s, char *t) { while ( (*s++ = *t++)!= \0 ) ; Versio 3: void kopioi( char *s, char *t) { while ( *s++ = *t++ ) ; Funktion otsikko on identtinen edellisen kalvon kanssa, vain viittaaminen alkioihin erinäköinen. Minimalistisen selkeä! Merkkijonovakiot ja osoittimet u Merkkijonovakio on yhtenäinen muistialue, jonka pääp äättää lopetusmerkki \0. u char *aamu = Kello soi! \a \a u char huomenta[] = Kello soi! \a \a huomenta: aamu: Kello soi! \a \a Kello soi! \a \a u Muistialueen (huomenta) yksittäisiin isiin alkioihin voidaan viitata u Osoitin aamu voidaan asettaa muualle, mutta osoitetun merkkijonon muutosyritysten tulos on epämääräinen 22

C assumes that programmer is intelligent enough to use all of its constructs wisely, and so few things are forbidden. C can be a very useful and elegant tool. People often dismiss C, claiming that it is responsible for a bad coding style. The bad coding style is not the fault of the language, but is controlled (and so caused) by the programmer. 23