Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 3

4.

A C nyelv függvényei
A C nyelv függvényei megfelelnek a Pascal eljárásainak vagy függvényeinek. A függvény kényelmes
lehetőséget biztosít a programozónak, hogy egy számítási részt önállóan kezelhető, zárt egységbe
foglaljon. Ezek a zárt egységek ezután szabadon felhasználhatók anélkül, hogy a konkrét
felépítésükkel, megvalósításukkal törődnünk kellene. Megfelelően tervezett és megvalósított
függvények esetén teljesen figyelmen kívül hagyhatjuk, hogy hogyan keletkezett a függvény értéke,
elegendő csak az eredményt tudni.

A függvénydefiníció általános alakja:

visszatérési típus függvénynév (paraméter-deklarációk, ha vannak)


{
deklarációk
utasítások
}

A függvénydefiníciók tetszőleges sorrendben szerepelhetnek, egy vagy több forrásállományban (bár


természetesen egy függvény nem osztható szét két forrásállományba).
Példaként nézzük meg, egy egyszerűsített hatványozó függvényt (csak kis egész számok egész hatványait képes
kiszámolni). A program két függvényt tartalmaz: a hatványozást megvalósító power függvényt és az azt hívó
main főprogramot (ami maga is függvény).

#include <stdio.h>

int power(int m, int n);

/* a hatványozó fv. ellenőrzése */


main()
{
int i;

for (i=0; i<10;++i)


printf(”%d %d\n”, i, powewr(2,i), power(-3,i));

return 0;
}
/* a power(m,n) fv. az m alapot az n-edik hatványra emeli, ahol n>=0 */
int power(int alap, int n)
{
int i,p;

p=1;
for (i=1;i<=n;++i)
p=p*alap;
return p;
}

A main a power függvényt kétszer hívja meg. Mindkétszer két argumentumot adunk át a power
függvénynek és az egy egész értékkel tér vissza. Egy aritmetikai kifejezésben a power(2,i) éppolyan egész
mennyiség mint 2 és i.
A power függvény első sora az

int power(int alap, int n)

a paraméterek (argumentumok) típusát és nevét, valamint a függvény visszatérésekor szolgáltatott értékének


típusát deklarálja. A függvény által használt paraméterek neve az adott függvényre nézve lokálisak, azaz
egyetlen más függvényben sem láthatók, bármely eljárás ugyanezeket a neveket minden gond nélkül saját
céljaira használhatja. Ugyanez igaz a függvényen belül deklarált változókra is.
Paraméternek evezzük a függvénydefiníció során zárójelben megadott változóneveket, és argumentumnak a
függvény hívása során átadott értékeket.
Ha a definícióból hiányzik a visszatérési típus, akkor a rendszer az int alapfeltételezéssel él. Amennyiben azt
akarjuk, hogy a függvény érték nélkül térjen vissza akkor a void kulcsszót kell használni.
A power függvényben kiszámított értéket a return utasítás adja vissza a hívó (jelen esetben a main)
függvénynek. A return utasítás után tetszőleges kifejezés állhat a
return kifejezés;
szintaktika szerint. Egy függvénynek nem feltétlenül szükséges értékkel visszatérni a hívó programba. Egy
kifejezés nélküli return utasítás visszaadja a vezérlést a hívó programnak, de nem ad át hasznos információt.
Ez történik akkor is, ha a vezérlés átlépi a függvény végét jelző jobb oldali kapcsos zárójelet (nincs return).
Természetesen a hívó függvénynek jogában áll nem figyelembe venni a visszaadott értéket.

Az

int power(int m, int n);

deklaráció a main előtt azt mondja meg, hogy a power függvény két egész típusú argumentumot vár és egész
típusú eredménnyel tér vissza. Ezt a deklarációt a függvényprototípusnak nevezzük, és meg kell hogy egyezzen a
függvény definíciójával és használatával. Természetesen a paraméterek neveinek nem kell egyezni, a függvény
prototípusában a paraméternevek opcionálisak. A power prototípusát így is írhatnánk:

int power(int, int);

A C nyelv sajátossága, hogy minden függvényargumentumot érték szerint adunk át. Ez azt jelenti, hogy a hívott
függvény mindig az argumentumok értékét kapja meg (átmeneti változókban), azok címe helyett. Tehát a C
nyelvben a hívott program nem férhet hozzá és nem változtathatja meg a hívó függvény változóit, csak a saját
átmeneti másolatával dolgozhat.
Az érték szerinti hívás mindenképpen előny. Felhasználásával sokkal tömörebb, kevesebb segédváltozót
tartalmazó program írható, mivel a hívott függvényben a paraméterek ugyanúgy kezelhetők, mint az inicializált
lokális változók.
Szükség esetén természetesen elérhető, hogy a hívott függvény megváltoztassa a hívó függvény valamelyik
változóját. Ehhez a hívott függvénynek meg kell kapnia a kérdéses változó címét a hívó függvénytől (ami a
változót megcímző mutató átadásával lehetséges) és a hívott függvényben a paramétert mutatóként kell
deklarálni, amelyen keresztül indirekten érhető el a hívó függvény változója.
A leírtak nem érvényesek a tömbökre. Ha argumentumként egy tömb nevét adjuk meg, akkor a függvénynek
átadott érték a tömb kezdetének helye (címe) lesz, a tömbelemek átmásolása nem történik meg.

A nem egész értékkel visszatérő függvények kezelése külön odafigyelést igényel. Tegyük fel hogy van egy

doble atof(char s[])

függvényünk mely a paraméterként kapott szöveget lebegőpontos számmá konvertálja.


Először az atof függvénynek deklarálni kell a visszatérési értékét, mivel az most nem int. Ezt a már ismert
módon a függvény neve előtt tehetjük meg. Másodszor, és ez legalább ilyen fontos, a hívó eljárással is tudatni
kell, hogy az atof visszatérési értéken nem int típusú. Ennek egyik módja, hogy az atof függvényt explicit
módon deklaráljuk a hívó eljárásban:

main()
{

double x, atof(char []);

x=atof(s);

}

A
double x, atof(char []);

deklaráció azt mondja ki, hogy az x egy double típusú változó, valamint az atof függvénynek egyetlen,
char[] típusú argumentuma van és visszatérési értéke double típusú.
A függvényt tehát következetesen, egymással összhangban kell deklarálni és definiálni. Ha egyetlen
forrásállományon belül ellentmondás van a függvény típusa és a hívásának típusa között, akkor ezt a hibát a
fordítóprogram jelezni fogja. De ha pl. az atof függvényt önállóan fordítjuk le (és ez legtöbbször így van),
akkor a hiba nem derül ki. Az atof visszaad valamilyen double értéket, amit a hívó int-ként kezel és ez
értelmetlen eredményhez vezet.
A típusillesztési hiba főként olyankor fordul elő, ha nincs függvényprototípus, és a függvény a kifejezés első
előfordulásakor, implicit módon van deklarálva. Ha korábban még nem deklarált név fordul elő egy kifejezésben
és a nevet bal oldali kerek zárójel követi, akkor arról a rendszer feltételezi, hogy függvény és a kifejezés
megfelelő részét a függvény deklarációjának tekinti.

A külső (extern) változók és függvények


A C nyelvű program külső objektumok – változók és függvények – halmaza. A függvények mindig külső
típusúak, mivel a C nyelv nem engedi meg, hogy egy függvény belsejében újabb függvényt definiáljunk.
Egy változó külső tárolási osztályú, ha bármelyik függvényen kívül definiáljuk. A külső változók globálisan
hozzáférhetők, azaz bármely függvény hozzáférhet neve alapján, ha valahol ezen a néven deklarálva lett.
Egy név érvényességi tartománya (hatásköre) az a programrész, amiben a nevet használhatjuk. A függvény
kezdetén deklarált változó érvényességi tartománya az a függvény, amelyben deklarálták. A külső változók vagy
függvények érvényességi tartománya a deklaráció helyén kezdődik és az éppen fordított forrásállomány végéig
tart. Másrészről, ha egy külső változóra a definiálása előtt hivatkozunk, vagy más forrásállományban definiáltuk,
mint ahol használjuk, akkor kötelező az extern deklaráció. A külső változókat csak a forrásállományok
egyikében kell definiálni, a többi állományban csak extern deklaráció van, amelyen keresztül a változók
elérhetők.

A statikus (static) változók és függvények


A külső változókra vagy függvényekre alkalmazott static deklaráció az objektum érvényességi tartományát
az éppen fordított forrásállomány fennmaradó részére korlátozza. A statikus tárolási osztály a normális
deklaráció elé írt static kulcsszóval deklarálható. Bár a külső statikus deklarációt leggyakrabban változókra
alkalmazzák, de függvényekre is használható. Normális körülmények között a függvények nevei globálisak, a
teljes program számára ismertek. Ha egy függvényt static tárolási osztályúnak deklarálunk, akkor a neve a
deklarációt tartalmazó forrásállományon kívül nem ismert. A statikus tárolási osztály belső változókra is
alkalmazható. A belső statikus változók a megfelelő függvényre nézve lokáliak, de állandóan megmaradnak
(nem szűnnek meg a függvényből való kilépés után). Ez azt jelenti, hogy a belső static deklarálású változók
a függvény saját, állandó tároló helyei lehetnek.

A typedef utasítás
A C nyelv typedef utasításával új adattípus-neveket hozhatunk létre. Pl. a

typedef int Hossz;

deklaráció bevezeti a Hossz típusnevet, mint az int típusnév szinonimáját.


Ki kell hangsúlyozni, hogy a typedef utasítás semmilyen értelemben nem hoz létre új adattípust, mindössze a
már meglévő adattípushoz rendel új típusnevet.
A typedef utasítást két okból szokták alkalmazni. Az első, hogy a paraméterezés a program
hordozhatóságánál okozhat gondokat. A typedef-fel deklarált adattípusok gépfüggetlenné tehetők a typedef
módosításával. A másik ok, hogy az így deklarált típusok javítják a program olvashatóságát.

You might also like