A InfoWiki wikiből
(Új oldal, tartalma: „<cim cim3="Numerikus kifejezések" cim2="Magasszintű Programozási Nyelvek I." cim1="Imperatív, procedurális nyelvek alapjai" prev="mp1/page150" next="mp1/page1...”) |
Aktuális változat (2009. október 15., 09:43) (lapforrás) |
||
11. sor: | 11. sor: | ||
<path p1="Kezdolap|Kezdőlap" p2="EBooks|Jegyzetek" p3="mp1/Nyitolap|Tartalomjegyzék" | <path p1="Kezdolap|Kezdőlap" p2="EBooks|Jegyzetek" p3="mp1/Nyitolap|Tartalomjegyzék" | ||
xx="-" | xx="-" | ||
- | w1="mp2 | + | w1="mp2/Nyitolap|Gyakorlatok" w2="mp1/Tematika|Vizsgatematika" w3="cs/Blog|Programok C# nyelven" |
/> | /> | ||
Aktuális változat
Példa
A harmadik generációs programozási nyelvek egyik nagy előnye, hogy numerikus kifejezéseket írhatunk. A korábbi generációkban (gépi kód, assembly) egy numerikus kifejezés kiértékelését lépésekre kellett bontani. Ezen lépéssorozat elolvasásával deríthető csak ki, hogy mi is az, amit éppen számolunk.
int r = 14; double a = 2*r*3.14;
A fenti példában az a változóta vonatkozó értékadó utasítás jobb oldalán egy numerikus kifejezés áll, három adattal, és két operátorral. Ismert, hogy egy értékadó utasítás akkor végrehajtható, ha a jobb oldal típusa megegyezik, vagy implicit módon konvertálható a bal oldal típusába.
Írjuk fel ezt az értékadó utasítást tisztán típusokkal:
double = int * int * double;
Határozzuk meg a jobb oldal típusát. Ehhez a kifejezésbeli operátorok végrehajtási sorrendjét kell ismerni. Ez esetben egyszerű a helyzet, mindkét operátorunk a szorzás operátor, ezek balról jobbra sorrendben hajtódnak végre:
Először végrehajtódik az int*int, amelynek eredménye szintén int. Ha az első szorzás után vizsgáljuk a kifejezést, akkor már csak ennyi van ott:
double = int * double;
Itt most gond van, mivel int*double következik.
Korábban volt már utalás arra, hogy nem egyforma típusú adatok közötti műveletvégzés során a háttérben típusegyeztető lépések történnek. Ennek oka, hogy a lebegőpontos ko-processzor csak egyforma adattípusok között tud műveletet végrehajtani, különböző típusok között nem (ennek is oka van persze, bővebben erről a Bevezetés az informatika-ba, illetve a Számítógép-architektúrák tárgyban lehet olvasni).
A típusegyeztetést az előző fejezetben nevén neveztük: implicit típuskonverzió hajtódik végre. Mivel double->int implicit típuskonverzió nincs, de int->double van, ezért a fordítóprogram itt automatikusan alkalmazza azt, és a fenti kifejezés double*double típusok között fog végrehajtódni, mely szorzásnak ez esetben az eredménye is double.
Ezzel meg is kaptuk a fenti kifejezés végeredményének a típusát. Ezt most a fordító összeveti a bal oldal típusával:
double = double;
Mivel a két oldal megegyezik, nem kell további implicit típuskonverziót alkalmazni sem - az értékadó utasítás típushelyes, tehát végrehajtható.
Numerikus kifejezések
A numerikus kifejezések kiértékelésének két szintje van:
- a konkrét végeredmény-értéktől függetlenül csupán a kifejezésben részt vevő típusok és operátorok ismeretében a kifejezés eredméynének típusa levezethető
- a kiértékelés során lépésenként egyszerűsítjük a kifejezést, egy lépésben egy operátort végrehajtva mindaddig, amíg a konkrét végerdményt meg nem kapjuk. Ennek során a műveleti prioritásokat és kötési szabályokat kell betartani.
Típuslevezetés
A kifejezés eredményének típusát a fordítóprogram vezeti le. Erre azért van szükség, hogy ezen típust összevethesse pl. az értékadó utasítás bal oldalának típusával, és eldönthesse, hogy kell-e (tud-e) alkalmazni implicit típuskonverzót, illetve az értékadó utasítás típushelyes-e.
A típuslevezetés során minden esetben csak egy konkrét operátor végrehajtását kell vizsgálni. Majd ezt a szabályt alkalmani újra-és-újra, amíg az egyszerűsített kifejezésünk egy elemű nem lesz. Ekkor megkaptuk a kifejezés eredmény-típusát. Tegyük fel, hogy a vizsgált kifejezés-rész A op B alakú (ahol A és B egy-egy típus, az op egy numerikus operátor, pl. összeadás, kivonás, stb).
- amennyiben A és B megegyezik, úgy az A op B végrehajtásának eredményének típusa is marad A típusú
- amennyiben A és B nem egyforma, de létezik implicit típuskonverió A->B irányban, akkor ezt a fordító ezen a ponton betervezi a végrehajtás menetébe. Innentől kezdve az op operátort két B típusú érték között kell végrehajtani, vagyis az eredmény típusa B lesz
- hasonlóan, ha létezik B->A implicit típuskonverzió, akkor az betervezésre kerül, az op két darab A típusú értéken lesz végrehajtva, és az eredmény típusa is A lesz
- amennyiben A és B nem egyezik meg, és egyiket sem lehet átalakítani implicit módon a másik típusára, akkor a numerikus kifejezésünk típus-helytelen. A fordítóprogram szintaktikai hibát jelez, és a fordítás ezen a ponton megáll.
Az utolsó eset nem jelent végleges problémát. Elképzelhető, hogy létezik explicit típuskonverzió vagy A->B vagy B->A irányban. A szintaktikai hiba esetén a programozó a megfelelő helyre beírhatja ezen explicit típuskonverziót (amennyiben ez nem okoz gondot), és újra próbálkozhat a fordítással.
Ami fontos észrevétel: egy A op B rész-kifejezés típusa vagy A vagy B lesz. Amennyiben A=B, úgy ezen egyforma típus. Amennyiben különbözőek, úgy a nagyobb típus lesz.
A fenti szabályok figyelembevételével, lépésenkét haladva tetszőleges bonyolultásgú kifejezés típusát le lehet vezetni.