Download c++ PDF

Titlec++
File Size1.4 MB
Total Pages186
Document Text Contents
Page 1

Robert Logožar

Uvod u programiranje
i

jezik C/C++

Page 93

85

Iznad varijable iX2 na stog se smješta kazaljka pI . Mada je njen sadržaj pI = 0012 FF68 za 4
manji u odnosu na prethodni primjer, jer su varijable iX1, iX2 pohranjene na adresama za 4
manjima, njen smisao je isti: ona upućuje na varijablu iX1.

Nakon smještaja kazaljke pI, kompilator nailazi na objavu poretka iY tvrdnjom:
int iY[cuN] = {0, } ;

Ovime su ujedno svi elementi poretka incijalizirani na vrijednost iY[i] = 0 (i = 0, 1, 2, … cuN-1 ).
Pošto poredak ima 100 elemenata duljine 4B, za njega je potrebno rezervirati ukupno 400d B =
= 190h B. Kompilator od adrese A(iP) = 0012 FF68 kazaljke iP oduzima heksadekadski broj
190h, i dobiva adresu početka poretka:

A( iP ) = 0012 FF60 − 0000 0190 = 0012 FDD0 .

Kompilator u svoju tablicu simbola, bilježi ime poretka, u našem slučaju iY , i tretira ga u bitnom
kao konstantu kazaljku, čija je vrijednost jednaka dobivenoj adresi. Dakle, dobivena adresa početnog,
ili nultog, elementa, smatra se i adresom poretka samog (vidjeti odjeljak kazaljke i poredci). Prilikom
izračuna adrese poretka mogu se pojaviti i dodatni zahtjevi za poravnanjem podataka, što će biti obra-
zloženo u sljedećem odjeljku.

Iako se varijable na stog smještaju prema manjim adresama — pa se tako i adresa poretka tvori
oduzimanjem njegove veličine od adrese prethodne varijable — razmještaj elemenata unutar poretka
je kao što bismo očekivali: adrese elemenata rastu linearno s porastom indeksa elementa. To je u skla-
du s gradivom izloženom u prethodnom poglavlju.

Sadržaj memorije na adresama koje su na stogu „iznad“ poretka, odnosno čiji su iznosi manji od
adrese poretka, nepoznat je i nevažan za naš programski odsječak. To je dio memorije koji je program
dobio na raspolaganje za smještaj lokalnih varijabli „na stog“, i koji je, barem za sada, ostao nepopu-
njen. Tu bi se smještale nove varijable, kad bi bile deklarirane.

U 2. dijelu programskog odsječka se, na isti način kao i u prethodnom primjeru, vrijednost na koju
pokazuje kazaljka pI, dakle vrijednost varijable iX1, pridružuje varijablama istog tipa. Sada su to
elementi poretka iY[0], iY[1], iY[99], čija je konačna vrijednost 0000 0001 prikazana na slici.

U našem primjeru, sve su varijable, uključujući kazaljke i elemente poretka, imale istu veličinu od
4B. Primijetimo da su sve smještene na adresama koje su djeljive s 4, tj. onima sa zadnjom znamen-
kom 0, 4, 8 ili C (pošto je baza heksadekadskog sustava Bh = 16 = 2

4 djeljiva s 4). Općenito, za tip
podataka T duljine t bajtova kažemo da je poravnat, ako mu je adresa na koju je smješten djeljiva
s t. Iz toga proizlazi da je tip char uvijek poravnat, da je tip short int poravnat ako je na parnim
adresama, itd…

Poravnatost podataka (engl. data alignement) vrlo je važna za učinkovitiji prijenos podatka iz
procesora u memoriju. Za dohvat poravnatog podatka potreban je minimalan broj sabirnčkih ciklusa,
konkretno, za tipove duljilne 4B je na sustavima s 32-bitrnom adresnom sabirnicom potreban upravo
jedan sabirnički ciklus. S druge strane, ukoliko takav podatak nije poravnat, tada će biti potrebna 2
sabirnička ciklusa, tj. duplo duže vrijeme. Da bi ostvarili poravnatost, prevodioci će u općenitom slu-
čaju ostavljati prazne bajtove. Npr. da smo u gornjem primjeru deklarirali varijablu tipa char veličine
1B, između varijabli veličine 4B, prevodilac bi 3 bajta ostavio prazna da sljedeća varijabla duljine
4B bude ponovo na adresi djeljivoj s 4 (detaljnije u dodatku Cxx).

Poravnatost poredaka prevodioci vrlo često tretiraju posebno. U našem je primjeru adresa poretka
sjela točno na „okruglu adresu“ djeljivu sa 16, tj. na adresu kojoj je zadnja znamenka 0. Za slučaj da
to nije tako, mnogi će prevodioci pomaknuti adresu poretka na prvu nižu okruglu adresu.* Na taj se


* Npr. GNU GCC u razvojnim okolinama kao što su Dev-Cpp, Code::Blocks.

Page 94

86



način osigurava brži rad se elementima poretka, tj. njihov brži premještaj unutar memorijskog sustava
glavne i priručne memorije. Da se ostvari taj cilj, žrtvuje se neiskorištenost do desetak bajtova, slično
kao što se za poravnanje pojedinih varijabli žrtvovalo nekoliko bajtova.

Dodatno, razvojne okoline nude mogućnost da se u tijeku razvoja programa gradi tzv. „debug“
inačica (engl. debug version) programa koja je posebice prilagođena da pomogne programeru pri
otklanjanju grešaka. Neke od njih će za pojedinačne varijable rezervirati dodatne bajtove kako bi se
olakšao proces nalaženja logičkih grešaka. Primjerice, MS Visual Studio od inačice 2005 za pohranu
svih varijabli rezervira dodatnih 8B za potrebe učinkovitijeg rada otklanjača pogrešaka.

Nakon što je program korektan, gradi se završna inačica (engl. release version) programa u kojoj
se za podatke rezerviraju minimalna potrebna mjesta uz uvažavanje poravanja podataka. Također, u
postupku optimizacije, koja vodi računa o detaljima rada procesora, vrše se dodatne promjene u svrhu
optimizacije brzine rada i utrošene memorije. Tako u svrhu boljeg pakiranja varijabli, kompilatori ih
često prerazmjeste tako da združuju istovrsne varijable i one manjih duljina, smanjujući na taj način
broj neiskorištenih bajtova (dodatak Cxx).

Memorijska
adresa:

Sadržaj memorije
(4 uzastopna bajta)

Značenje
sadržaja



… … … … … …

0012 FDC8 XXXX XXXX –

0012 FDCC XXXX XXXX –

0012 FDD0 0000 0001 iY [0]

0012 FDD4 0000 0001 iY [1]

… … … … … …

… … … … … …

… … … … … …

0012 FF50 0000 0000 iY[98]

0012 FF54 0000 0001 iY[99]

0012 FF60 0012 FF68 pI
Smjer
rasta
stoga

0012 FF64 FFFF FFFE iX2

0012 FF68 0000 0001 iX1

0012 FF6C 0000 0064 cuN = 100d

Dno stoga: 0012 FF70 XXXX XXXX –

0012 FF74 XXXX XXXX –

… … … … … …

Slika 7.3 Prikaz memorijske pohrane varijabli i kazaljki deklariranih u primjeru 7.2. Stanje me-
morije nakon izvršenja 1. i 2. dijela programskog odsječka. Prva je deklarirana konstanta cuN tipa
int koja se smješta na adresu 0012 FF6C , za 4 manju od dna stoga označenog adresom 0012 FF70. Za-
tim na stogu slijede varijable iX1, iX2 te pI, kao u prethodnom primjeru. Dodatno, deklariran je pore-
dak iY tipa int, sa cuN = 100 elemenata, što je glede duljine pojedinog elementa i ukupne duljine je-
dnako primjeru poretka sa slike 6.1 u prethodnom poglavlju. Adresu poretka kompilator dobiva tako da
od adrese sljed Asdfg Raspored ovih elemenata u memoriji ijede jedeća varijabla iX1 istog tipa, smje-
šta se na adresu za 4 manju od prethodne, tj. na 0012 019C. Iza toga se smještaju sljedeće dvije varijab-
le, od kojih je druga kazaljka na cjelobrojni tip. Njoj se u zadnjoj tvrdnji prvog dijela programskog koda
pridružuje adresa varijable iX1 (masno pisana vrijdenost). Strelice sugeriraju značenje pokazivačkog ti-
pa: njegova vrijednost je adresa koja pokazuje gdje se nalazi promatrana programska tvorba (varijabla,
poredak, objekt, vidi dalje). Navedene vrijednosti adresa su fiktivne. Stvarne adrese ovise o verziji kom-
pilatora i operacijskom sustavu. Čitatelj ih može provjeriti u svojim razvojnim okolinama.

Page 185

177

Array = &Array[0] = EBP – 10h – t × n ,

a adresa posljednjeg člana:
&Array[n - 1] = EBP – 10h – t × n + t × ( n – 1 ) = EBP – 10h – t .

Dakle, iako je prostor za lokalne varijable rezerviran na korisničkom stogu, one se ne referiraju stan-
dardnim stožnim operacijama. Jasno je da to nikako ne bi bilo u redu, jer npr. stožna operacija uzima-
nja sa stoga "skida" element sa stoga, a lokalne varijable moramo moći referirati dokle god smo unu-
tar funkcije gdje je ona deklarirana. Do lokalnih varijabli se dolazi kako je opisano, dodavanjem fik-
snih (negativnih) posmaka (engl. displacement, offset) adresi pohranjenoj u registru EBP, na gore opi-
sani način.

Prijenos argumenata i rezultata funkcije. Argumenti funkcije se također prirodno prenose preko
stoga. U pozivnoj funkciji fA prevodilac prije strojne instrukcije poziva (call), stavlja na stog stvarne
argumente poziva koji se moraju po redoslijedu, tipu i broju slagati s fiktivnim argumentima navede-
nim u zaglavnoj datoteci date funkcije. Ništa drugo pozivna funkcija fA ne mora znati o pozvanoj
funkciji fB, što je u skladu s važnim načelom programiranja, tzv. principom skrivanja (nenužne) in-
formacije. Nakon što su na stog pospremljeni argumenti poziva, prevodilac u kod ugrađuje strojnu
instrukciju call Adress_fB koja najprije na stog posprema adresu povratka u fA (adresu instrukcije
neposredno iza instrukcije call), a zatim vrši grananje (skok) na adresu Adress_fB. Sada kontrolu iz-
vođenja preuzima funkcija fB koja će izgraditi svoj aktivacijski slog na stogu kao što je već opisano,
tj. pohranom sadržaja registra EBP na stog, itd. redom.

Prilikom završetka funkcije fB povratna vrijednost funkcije koja nije tipa void može se vratiti pre-
ko rezerviranog mjesta na stogu (koje je pozivna funkcija fA također mogla rezervirati zajedno s ar-
gumentima poziva), ili preko dogovorenog registra (EAX). Potom se sa stoga «miču» sve lokalne va-
rijable jednostavnim stavljanjem vrijednosti EBP u ESP (dakle radi se o brzoj registarskoj operaciji
koja ništa ne mora raditi s memorijskim operandima). Tako je čitav aktivacijski slog fB «nestao»,
došli smo do mjesta na stogu gdje se nalazila stara vrijednost registra EBP. Tu vrijednost sada skine-
mo sa stoga i premjestimo u EBP, čime je sve pripremljeno za povratak u funkciju fA. Na tom mjestu
prevodilac ugrađuje instrukciju povratka (ret), koja sa stoga skida adresu povratka i stavlja je u prog-
ramsko brojilo (na Intelovim procesorima to je registar IP, engl. Instruction Pointer, tj. kazaljka in-
strukcije). Time se kontrola izvođenja vraća na pozivnu funkciju fA, koja se nastavlja izvoditi na in-
strukciji neposredno iza instrukcije poziva (call).

Page 186

178





Literatura
1. B. W. Kernighan, D. M. Ritchie, The C Programming Language, 2nd ed., Upper Saddle River, NJ,

Prentice Hall, 1988.
2. B. Stroustrup: The C++ Programming Language, 3rd ed., Reading, Massachusetts, 1997.
3. C. S. Horstmann, Mastering Object-Oriented Design in C++, John Wiley & Sons, New York,

1995.
4. A. B. Tucker at al. Fundamentals of Computing I & II, C++ Edition, McGraw-Hill, New York,

1995.
5. Motik, Šribar: Demistificrani C++, 2. izdanje Element Zagreb, 2001.
6. L. Budin, Informatika 1, udžbenik za 1. razred gimnazije, Element d.o.o., Zagreb, 2001.
7. Wikipedia članak: www.wikipedia.org. – članak imena navedenog u tekstu.
8. Microsoft Developers Network (MSDN) Library, http://msdn.microsoft.com/en-us/library/ .

Similer Documents