815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 3 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten muuttujiin liittyvät kysymykset. Tehtävä 1. Määritä muuttujien max_num, lista, i, strlist, pituus, lisays ja j tyyppiin ja muistin allokoimiseen liittyvän sidonnan tyypit sekä muuttujien elinajat seuraavassa C++-ohjelmassa: #include <iostream> using namespace std; int max_num = 100; char *lista = 0; char* merkit(int len, int add) int i; if (len < max_num) char *strlist = new char[len]; for (i = 0; i < len; i++) strlist[i] = i+ add; return strlist; return 0; int main() static int pituus=5,lisays=60; lista=merkit(pituus, lisays); if (lista!= 0) int j; for (j = 0; j < pituus; j++) cout << lista[j] << " "; delete [] lista; return 0; Määritä myös lueteltujen muuttujien näkyvyysalueet.
Vastaus. Sidonta jaetaan staattiseen ja dynaamiseen. Staattinen sidonta tapahtuu viimeistään ohjelmaa käännettäessä ja dynaaminen ohjelmaa ajettaessa. Koska C++ on C- kielen ja useimpien muiden imperatiivisten ohjelmointikielten tapaan staattisesti tyypitetty, kaikkien muuttujien tyyppi määräytyy käännösaikaisesti eli staattisesti. Muuttujat voivat olla muistinvaraukseltaan staattisia, pinodynaamisia tai kekodynaamisia. Globaalit muuttujat ovat muistinvaraukseltaan staattisia, paikalliset muuttujat pinodynaamisia, ellei niitä erikseen määritellä staattisiksi. Muuttujien muistin allokoinnin tyyppi, elinaika ja näkyvyysalue on merkitty seuraavaan taulukkoon: muuttuja muistinvarauksen tyyppi elinaika näkyvyysalue max_num staattinen ohjelma ohjelma lista staattinen Huom: osoittaa kekodynaamiseen taulukkoon ohjelma ohjelma i pinodynaaminen merkit() merkit() strlist pinodynaaminen Huom: osoittaa kekodynaamiseen taulukkoon if(len<max_num) - lohko if (len < max_num) -lohko pituus staattinen ohjelma main() lisays staattinen ohjelma main() j pinodynaaminen if(lista!=0) -lohko if(lista!= 0) -lohko Huomaa, että muuttujat lista ja strlist ovat osoitinmuuttujia, joista edellinen on globaali ja sellaisena staattinen muistinvaraukseltaan. Jälkimmäinen on paikallinen muuttuja ja siten pinodynaaminen. Näistä kumpikin osoittaa kuitenkin kekodynaamisesti varattuun taulukkoon, jonka elinaika ohjelmassa ulottuu sen varaamisesta (merkit-funktiossa) sen vapauttamiseen (main-funktion loppuun). Huomaa myös, että pinodynaamisten muuttujien elinaika on läheisesti sidoksissa niiden näkyvyysalueeseen.
Tehtävä 2. Tarkastellaan C-ohjelman osaa int a, b, c; int d,e; int f; int x,y,z; Oletetaan, että yhden int-tyyppisen kokonaisluvun esittämiseen kuluu neljä tavua muistia. Kuinka paljon muistia kaikkiaan tarvitaan edellisen ohjelman osan muuttujille? Vastaus. Paikalliset muuttujat varataan pinomuistista kun tullaan muuttujien sisältämään lohkoon. Kun lohkosta poistutaan, voidaan muuttujien vaatima muisti vapauttaa. Pinoa käytettäessä tämä tarkoittaa, että pinon huipun osoitinta siirretään aiemmaksi ja uusia arvoja voidaan kirjoittaa vapautuneen osan päälle. Kun tehtävän ohjelmassa astutaan uloimpaan lohkoon, pinon päältä varataan tila kolmelle int-muuttujalle ja varattuun tilaan kirjoitetaan muuttujien a,b ja c arvot. Saavuttaessa sisempään lohkoon tarvitaan näiden lisäksi tila muuttujille d ja e. Edelleen mentäessä vielä sisempään lohkoon tarvitaan vielä tila muuttujalle f. Tällä hetkellä on varattu tilaa kuudelle int-muuttujalle. Kun poistutaan lohkosta, muuttujaa f ei enää tarvita, ja kun poistutaan vielä toiseksi sisimmästä lohkosta, ei enää tarvita muuttujia d ja e. Tilaa on nyt varattu kolmelle muuttujalle ja kun saavutaan seuraavaan lohkoon tarvitaan pinossa tilaa vielä muuttujille x,y ja z. Näin ollen missään vaiheessa pinossa ei tarvitse säilyttää ohjelman muuttujista kuutta enempää. Siis tarvitaan 24 tavua pinomuistia käsiteltäessä ohjelman muuttujia. Tehtävä 3. Kirjoita FORTRAN -ohjelma, joka osoittaa, että FORTRANin muuttujat ovat staattisia. Helpoimmin tämä tapahtuu kirjoittamalla aliohjelma, jonka paikallista muuttujaa kasvatetaan joka kutsulla ja tulostetaan muuttujan arvo. FORTRANin aliohjelma (kun parametreja ei välitetä) on muotoa SUBROUTINE ALI... Aliohjelman koodi RETURN END ja sitä kutsutaan pääohjelmasta kutsulla CALL ALI
Muuttujan voi alustaa sen esittelyn jälkeen DATA -lauseella seuraavasti INTEGER LUKU DATA LUKU/50/ Voit käyttää FORTRAN-ohjelman mallina ensimmäisen harjoituksen materiaalin Ekaohj.for-tiedostoa. Testaa ohjelmaasi verkon Ideone-kääntäjällä (https://ideone.com/). Vastaus. Harjoituksen yhteyteen on linkitetty tiedosto Statohj.for, jossa on asiaa selvittävä FORTRAN-ohjelma. Ohjelman aliohjelmassa LASKE on paikallinen muuttuja LUKU. Muuttuja alustetaan nollaksi ja sitä kasvatetaan joka kutsukerralla. Mikäli funktion muuttuja olisi muistinvaraukseltaan dynaaminen, se saisi saman alkuarvon jokaisella kutsukerralla. Kun ajetaan ohjelma, havaitaan, että muuttuja säilyttää arvonsa kutsujen välillä, joten muuttuja on staattinen. Tehtävä 4. Kirjoita C-kielinen ohjelma, jossa luodaan kaksi lueteltua tietotyyppiä, yksi viikonpäiville ja toinen kuukausille. Esittele ohjelmassasi muuttuja kummastakin tietotyypistä. Testaa seuraavia asioita: 1. Voiko eri tietotyyppien muuttujia vertailla? 2. Voiko väärän tietotyypin arvoa sijoittaa muuttujaan? 3. Voiko eri tietotyyppien arvoille tehdä aritmeettisia operaatioita? 4. Voiko muuttujiin sijoittaa mielivaltaisia kokonaislukuarvoja? Mitä voit päätellä C-kielen luetellun tietotyypin luotettavuudesta? Vastaus. Harjoituksen yhteyteen on linkitetty tiedosto H3T4_C_Luetellut.c, jossa on testattu tehtävän ominaisuuksia. Testeistä huomataan, että C käsittelee lueteltuja tietotyyppejä kokonaislukuina, joille kaikki mainitut operaatiot ovat sallittuja. Näin ollen tietotyypin luotettavuus on erittäin vähäinen. Lueteltu tyyppi on silti tässäkin muodossa kätevä ohjelman luettavuuden ja kirjoitettavuuden kannalta. Tehtävä 5. Kirjoita C-kielinen ohjelma, joka tulostaa 5*10-kokoisen kaksiulotteisen kokonaislukutaulukon käyttämällä pelkästään osoittimia taulukon indeksioperaattorin [] asemasta. Vastaus. Taulukon tulostaminen voidaan tehdä osoitinaritmetiikalla ottamalla huomioon, että C-kielessä taulukon nimi on myös osoitin taulukon ensimmäiseen alkioon ja että kaksiulotteinen taulukko tallennetaan vaakarivi kerrallaan. Näin ollen, kun taulukossa taulu on N saraketta, niin taulukon alkio taulu[i][j] = *(taulu + j + i*n). Tämä on otettu huomioon linkitetyssä esimerkkiohjelmassa H3_T5_Taulukko.c, jossa taulukko tulostetaan aliohjelmassa. Aliohjelma ottaa parametrinaan osoittimen taulukkoon ja taulukon rivien ja sarakkeiden lukumäärän.
Tehtävä 6. Kirjoita C-ohjelma, jossa on ainakin kolme tapausta automaattisen tyypinmuunnoksen aiheuttamasta virheestä. Vihje: Eri numeeristen tyyppien sijoituksista ja operaatioista saattaa tulla virheellisiä tuloksia. Vastaus. Tyypillisesti kaventavat muunnokset aiheuttavat ongelmia. Harjoituksen yhteyteen linkitetyssä tiedostossa H3T6_Muunnokset.c, sisältää muutamia esimerkkejä tällaisista. C-kielessä tehdään varsin paljon pakotettuja tyypinmuunnoksia, joten esimerkkejä on mahdollista keksiä monia.