C-ohjelmointi: Osoittimet

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

C-ohjelmointi, kevät 2006: Funktiot

C-ohjelmointi: Funktiot. Luento: viikko 2

C-ohjelmointi, syksy 2008: Funktiot

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

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

C-ohjelmointi Luento 5: Osoittimet Tiina Niklander

Rakenteiset tietotyypit Moniulotteiset taulukot

C-ohjelmointi Luento 5: Osoittimet

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

Lyhyt kertaus osoittimista

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Osoitin ja viittaus C++:ssa

C-ohjelmointi, kevät t 2006: Funktiot. Luento 4, ti Tiina Niklander

Tietueet. Tietueiden määrittely

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

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Jakso 4 Aliohjelmien toteutus

Osoittimet ja taulukot

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

C-ohjelmointi, syksy 2006

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

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

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

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

Jakso 4 Aliohjelmien toteutus

C-ohjelmointi, syksy 2006: Funktiot

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

Luento 4 Aliohjelmien toteutus

Loppukurssin järjestelyt C:n edistyneet piirteet

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Loppukurssin järjestelyt

Osoittimet ja taulukot

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

Jakso 4 Aliohjelmien toteutus

TIETORAKENTEET JA ALGORITMIT

Dynaaminen muisti Rakenteiset tietotyypit

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

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

Tietorakenteet ja algoritmit

Ohjelmointi 1 Taulukot ja merkkijonot

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

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

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

ITKP102 Ohjelmointi 1 (6 op)

Moduli 4: Moniulotteiset taulukot & Bittioperaatiot

Luento 4 Aliohjelmien toteutus

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

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

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

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Luento 4 Aliohjelmien toteutus

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

Moduli 5: Kehittyneitä piirteitä

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

Taulukot. Jukka Harju, Jukka Juslin

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

Harjoitustyö: virtuaalikone

ITKP102 Ohjelmointi 1 (6 op)

7. Oliot ja viitteet 7.1

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

Moduli 2: Osoittimet ja taulukot. Joel Huttunen

Java-kielen perusteet

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

Tietorakenteet ja algoritmit

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

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

Tieto- ja tallennusrakenteet

7/20: Paketti kasassa ensimmäistä kertaa

Harjoitus 4 (viikko 47)

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ö

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

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

Tietorakenteet ja algoritmit

ITKP102 Ohjelmointi 1 (6 op)

Tieto ja sen osoite (3) Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Osoitinmuuttujat. Tieto ja sen osoite (5)

Listarakenne (ArrayList-luokka)

Tietotyypit ja operaattorit

Java kahdessa tunnissa. Jyry Suvilehto

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

3. Binääripuu, Java-toteutus

Tietorakenteet ja algoritmit

Olio-ohjelmointi Javalla

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Java-kielen perusteet

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

Tietorakenteet ja algoritmit

13 Operaattoreiden ylimäärittelyjä

A TIETORAKENTEET JA ALGORITMIT

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

1. Omat operaatiot 1.1

Olio-ohjelmointi Syntaksikokoelma

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

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

Transkriptio:

C-ohjelmointi: Osoittimet Liisa Marttinen & Tiina Niklander 22.2.2005 Muistinhallinta Java vs C Luokka on viittaustyypin määritelmä ja olio on viittaustyypin ilmentymä Muistinhallinta on implisiittistä. Java suoritusympäristö varaa muistia uusille olioille aina oliota luotaessa Roskienkeruu vapauttaa muistia eli poistaa muistista ne oliot, joihin ei enää ole viittauksia Mikä sitten on olioviite???? (No se on oikeastaan osoitin) Ei luokkia, mutta kuitenkin tietorakenteita ja osoittimia Eksplisiittinen muistinhallinta. Ohjelman on varattava muistia uusille tietorakenteille. Eksplisiittinen vapaus. Ohjelman on vapautettava tarpeeton muisti. Osoittimet ovat oikeastaan vain viittauksia muistissa oleviin tietoalkioihin 1

C osoittimet Osoitin on muuttuja, jonka arvona on toisen muuttujan osoite. Osoittimet ja taulukot ovat läheistä sukua. Osoittimia voi käyttää kuten taulukoita ja taulukon nimeä voi käyttää kuten vakio-osoitinta (const) Osoittimien käyttö perustuu siihen, että useimpien tietokoneiden muisti voidaan kuvata ikään kuin valtavana yksiulotteisena taulukkona. Kaikki ohjelmat ja data sijaitsevat tässä taulukossa. Osoitin on oikeastaan indeksi johonkin kohtaan muistia. Osoitinmuuttuja on eräänlainen viitta, jonka avulla päästään käsiksi toiseen muuttujaan. TITO Xptr DC 0 X DC 12 LOAD R1, =X STORE R1, Xptr LOAD R2, X LOAD R3, @Xptr Tieto ja sen osoite (3) ; R1 230 muisti Xptr=225: 230 ; R2 12 12345 ; R3 12 12556 Muuttujan X osoite on 230 128765 Muuttujan X arvo on 12 12222 Osoitinmuuttujan (pointterin) Xptr osoite on 225 X=230: 12 Osoitinmuuttujan Xptr arvo on 230 12998 jonkun tiedon osoite (nyt X:n osoite) Osoitinmuuttujan Xptr osoittaman kokonaisluvun arvo on 12 C-kieli: Y = *ptrx /* ei prtx:n arvo, mutta ptrx:n osoittaman muuttujan arvo */ 2

Operaatiot p = &c c = *p c = **r p = q osoitteen otto osoitetun muuttujan arvo - - (Nyt vain kaksi osoitinta peräkkäin) samantyyppiset osoittimet p+i p-i p-q p taulukko, i sopivan kokoinen kok.luku saman taulukon osoittimia ja q<p p < q p == q p ja q saman taulukon osoittimia *ip++ (*ip)++ osoittimen arvo kasvaa yhdellä osoitetun muuttujan arvo kasvaa yhdellä! KOODI ESIMERKKI: int main(int argc, char** argv) int x=1, y=2, z[10]; int *ip; int *p, q; int *r, *s; ip = &x; y = *ip; /* y = x =1 */ *ip = 0; /* x = 0 */ ip = &z[0]; HUOM: p on osoitin ja q tavallinen kokonaisluku x y z ip 1 2 0 1 double atof(char * string); Funktion parametrina osoitin on erittäin tavallinen 3

Taulukot c:ssä Taulukko on vain jono peräkkäisiä olioita, joilla on yhteinen nimi. Esim. int a[15] on 15 peräkkäisen kokonaisluvun jono. Taulukon nimi on osoitin, jonka arvona on ensimmäisen alkion osoite. Näin nimi osoittaa ensimmäiseen alkioon. Osoitinhan oli muuttuja, jonka arvona on muistiosoite. Sijoitus pa = &a[0] asettaa pa:n arvoksi a:n ensimmäisen alkion osoitteen Koska tuo on myös a:n arvo, voidaan kirjoittaa pa = a Osoitin käyttäytyy kuin taulukko. Syy osoitinaritmetiikka. Osoitinaritmetiikka Osoittimen voidaan katsoa osoittavan yhtenäisen alkiojonon ensimmäiseen alkioon (kuten taulukko) Alkioon i viitataan lisäämällä i osoitinmuuttujan arvoon: pa+i Osoitinaritmetiikka toimii viitattavan tyypin koosta riippumatta. pa+1 viittaa aina seuraavaan samantyyppiseen alkioon. Alkion arvo saadaan siis lausekkeella *(pa+i) Yleensä käytetään taulukkomaista viittausta pa[i] Osoitimen arvo NULL ei osoita mihinkään 4

Taulukko parametrina Funktiolle välitetään arvoparametrina kopio taulukon nimestä, eli osoite ensimmäiseen alkioon. Tästä seuraa, että taulukot ovat muuttujaparametreja ja funktio voi muuttaa alkioiden sisältöjä. Funktion parametrina char s[] char *s merkitsevät samaa asiaa. Käytä jälkimmäistä epäselvyyksien vuoksi. Koska kyseessä on osoitinmuuttuja eli taulukon nimi. HUOM: Parametrissa ei ole taulukon kokoa, koska kyseessä on osoitin eikä muistialue! #include <stdio.h> Esimerkki 2: merkkijonon kopiointi Käytetään taulukoita! void kopioi( char *s, char *t) int i =0; while ( (s[i] = t[i])!= \0 ) i++; Merkkijonotaulukot parametrina. Oikeasti osoittimet taulukoiden alkuihin. int main (void) Viitataan taulukon alkioihin char taalta [] = Tämä kopioidaan., yksi kerrallaan tanne[50]; kopioi ( tanne, taalta); printf( %s\n, tanne); kopioi ( tanne, taalta); printf( %s\n, tanne); return 0; 5

Esimerkki 2: merkkijonon kopiointi - jatkuu Käytetään osoittimia! Versio 1: Versio 2: void kopioi( char *s, char *t) while ( (*s = *t)!= \0 ) s++; t++; Versio 3: void kopioi( char *s, char *t) while ( *s++ = *t++ ) ; void kopioi( char *s, char *t) while ( (*s++ = *t++)!= \0 ) ; Funktion prototyyppi on identtinen taulukkoversion kanssa. Minimalistisen selkeä! Merkkijonovakiot ja osoittimet Merkkijonovakio on merkkitaulukko, jonka päättää lopetusmerkki \0. char *aamu = Kello soi! \a \a char huomenta[] = Kello soi! \a \a huomenta: Kello soi! \a \a aamu:. Kello soi! \a \a Taulukon (huomenta) yksittäisiin alkioihin voidaan viitata Osoitin aamu voidaan asettaa muualle, mutta osoitetun merkkijonon muutosyritysten tulos on epämääräinen 6

Osoitintaulukot kk tammi helmi huhti maalis touko kesä huono Koska osoitin on muuttuja, myös sen arvo voidaan osoittaa. Näin saadaan osoitin osoittimeen: int **a; Samoin voidaan määritellä taulukollinen osoittimia: int *t[10]; Nämä ovat suhteellisen harvinaisia paitsi komentoriviparametrien käsittelyssä. heinä elo syys loka marras joulu 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] ); Funktio-osoittimet Vaikka funktiot eivät ole muuttujia, niin niilläkin on osoite muistissa (kts. esim. TTK-91 konekieli). Tähän osoitteeseen voi viitata funktio-osoittimen avulla. Osoitin määritellään seuraavasti paluutyyppi (*nimi) (parametrilista); int (*lfptr) (char[], int); lfptr = getline; /* kun int getline(char s[], int len); */ Funktio-osoittimen avulla, voidaan eri kutsukerroilla kutsua eri funktiota. Näin voidaan rakentaa yleisiä aliohjelmia. (Esim. stdlib.h:ssa on funktio qsort, joka saa parametrina järjestysfunktion) 7

Funktiotaulukko: include/linux/quota.h 231 /* Operations which must be implemented by each quota format */ 232 struct quota_format_ops 233 int (*check_quota_file)(struct super_block *sb, int type); /* Detect whether file is in our format */ 234 int (*read_file_info)(struct super_block *sb, int type); /* Read main info about file - called on quotaon() */ 235 int (*write_file_info)(struct super_block *sb, int type); /* Write main info about file */ 236 int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */ 237 int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */ 238 int (*commit_dqblk)(struct dquot *dquot); /* Write structure for one user */ 239 int (*release_dqblk)(struct dquot *dquot); /* Called when last reference to dquot is being dropped */ 240 ; Tietueet (tai rakenteet) Tietue on kokoelma muuttujia (kenttiä), jotka voivat olla keskenään eri tyyppisiä. Rakenteeseen viitataan yhdellä nimellä. struct nimi kentät; ; Esimerkki: määrittely ei vielä varaa tilaa struct point int x; int y; Muuttujat määritellään käyttäen rakenteen nimeä: struct point p1, p2, p3; Rakenteen kenttään viitataan operaattorilla piste. p1.x = 2 * p2.y; 8

Rakenteille sallitut operaatiot Voidaan kopioida toisen rakenteen sisällöksi (p1=p2) Osoite voidaan ottaa &-operaattorilla Kenttiin voidaan viitata.-operaattorilla Voidaan alustaa määrittelyvaiheessa struct point p4 = 1, 5; typedef struct LogItemType TRID trid; int oper; int len; char data[256]; LogItemType; LogItemType logitems[200]; Osoittimet rakenteisiin Osoittimet rakenteisiin ovat samanlaisia kuin muutkin osoittimet. struct point *pp; pp = &p4; printf( orig (%d, %d)\n, (*pp).x, (*pp).y); Osoittimet ovat niin yleisiä, että tuo muoto (*mtuja).kenttä on lyhennetty muotoon muuttuja->kenttä. Yo. uusiksi printf( orig (%d, %d)\n, pp->x, pp->y); Operaattorit., ->, [] ja () ovat ylimmällä presedenssitasolla ja ryhmitellään vasemmalta oikealle. Käytä sulkuja, jos olet epävarma 9

sizeof ja union Varatun tilan saa selville sizeof-operaattorilla (funktiolla) sizeof(struct point); sizeof(p1); sizeof(&p1); sizeof(double); Union on rakenteen erikoistapaus union u_tag int ival; float fval; char * sval; ; Arvot jakavat saman muistialueen eli käytännössä ovat vaihtoehtoisia. malloc, calloc ja free void * on yleinen osoitin, joka voi osoittaa millaiseen rakenteeseen tahansa. void *malloc (size_t size); varaa muistia size tavua ja palauttaa osoittimen varatun muistin alkuun. malloc palauttaa NULL, jos muistin varaus ei onnistu. void *calloc (size_t nobj, size_t size); * calloc on kuten malloc, mutta varattavan muistin määrä on nobj*size tavua ja muisti nollataan. void *realloc (void *p, size_t size); * realloc muuttaa parametrina annetun osoittimen p osoittaman varatun muistialueen kokoa. void free (void *p); * free vapauttaa dynaamisesti varatun muistin takaisin käyttöjärjestelmälle. 10

Paluuarvon tarkistus! Hyvään ohjelmointitapaan kuuluu, että aina tarkistetaan funktion palauttama arvo ja toimitaan sen mukaan. Erityisen tärkeää tämä on mm. muistin varauksen yhteydessä. if (k=malloc(sizeof(double))) error; /* varaus epäonnistui, toivuttava tai lopetettava */ /* muistin varaus onnistui ja voidaan jatkaa normaalisti */ Abstrakti tietorakenne Abstrakti tietorakenne toteuttaa oman toiminnallisuutensa funktioiden ja omien rakenteiden kautta. Oliomaailmassa näitä vastaavat luokat ja niiden metodit, mutta c:ssä ohjelmoija on vastuussa niiden käytöstä. Void tyyppi mahdollistaa geneerisen listan, pinon, hajautustaulun yms. toteutuksen. Todellinen alkio määräytyy tyyppimuunnoksen kautta. Toteutetaan yleensä omaan.c - tiedostoonsa (tai kirjastoonsa) ja sillä on usein oma.h tiedoston käyttäjiään varten Esimerkiksi linuxin kernelin koodissa on vaikkapa tiedosto include/linux/list.h (joka tarjoaa listan toteutuksen) (kts. www-sivu http://lxr.linux.no/source/include/linux/list.h ) 11

Osoittimiin liittyviä käytänteitä (osa 1) Geneeristä osoitinta (void *p) voidaan tyyppimuunnoksen avulla käyttää käsiteltäessä tietyn tyyppistä muuttujaa *(double *)p Muistinvaraus n kappaleelle kokonaislukuja int *p; if ((p=malloc(n*sizeof(int))) == NULL) error; Muistin vapautus: muista aina tehdä free(p); p=null; i. alkio p[i] (mieluimmin kuin *(p+i) ) Lohkon läpikäynti for (pi = p; pi < p+size; pi++) käytä läpikäynnissä osoitinta pi Osoittimiin liittyviä käytänteitä (osa 2) Viiteparametri 1. Prototyypissä muodollisena parametrina osoitin void f(int *pp) 2. Funktion sisällä käytä osoittimen osoittamaa arvoa *pp 3. Kutsussa todellisena parametrina tav. muuttuja f(&mtja); 4. Kutsussa todellisena parametrina osoitinmuuttuja f(osmtja); Tietuetaulukon läpikäynti for (p = block; p < block + n*elsize; p+= elsize) i. tietue p = block + i*elsize 12

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. 13