Gyakori első próbálkozás az alábbi függvény:
void plusplus_plusplus(int a)
{
a=a+2;
}
Teszteljük a megoldást!
void plusplus_plusplus(int);
int main()
{
int a = 0;
/* a plusplus_plusplus függvény meghívása */
plusplus_plusplus(a);
printf("%d\n",a);
return 0;
}
void plusplus_plusplus(int a)
{
a=a+2;
}
Jól látható, hogy a függvény neve két helyen jelenik meg: először csak a fejlécét adjuk meg, ezzel megadjuk a fordítónak, hogy van egy plusplus_plusplus nevű függvényünk, amelyet egy egész típusú paraméterrel kell meghívni. Ezt hívják a függvény deklarációjának vagy prototípusának. Így amikor a main függvény plusplus_plusplus(a); sorához érkezik a fordító, tudja, hogy létezik egy ilyen függvény, még akkor is, ha odaáig még nem ért el a program feldolgozásában. Itt jegyezzük meg, hogy a .h állományok függvények prototípusait tartalmazzák (például az stdio.h többek között a scanf és a printf prototípusát).
Természetesen a fordítónak nem elég a hivatkozás módját ismerni, amit a prototípus ad meg, hanem a függvény törzsére is szükség van, azt is meg kell adnunk: más szóval definiáljuk a függvényt.
A program lefuttatása nem a kívánt eredményt adja, a kimenet az a változó eredeti értéke: 0.
Ennek az oka a következő: a paraméterátadás során a paraméter értéke lemásolódik egy másik memóriarekeszbe, így a main függvényben definiált a változónak semmi köze nincs a plusplus_plusplus függvény paraméterlistájában megjelenő a változóhoz, leszámítva azt, hogy a függvény hívásakor az átadott a változó lesz a plusplus_plusplus függvény a változójának kezdeti értéke. Ezek után a plusplus_plusplus függvényben hiába változtatjuk meg az a változót, a main függvénybeli a változóra ez nincs hatással, hiszen annak csak az értékét kapta meg a függvény. Ezt a paraméterátadási módot érték szerinti paraméterátadásnak hívjuk. A C nyelvben csak érték szerinti paraméterátadás létezik. Hogy írhatnánk mégis olyan függvényt, amely megváltoztatja a paraméter értékét? A megoldás: pointerekkel. Módosítsuk a függvényt az alábbi módon:
void plusplus_plusplus(int* pa)
{
(*pa)=(*pa)+2;
}
A változás jól láthatóan annyi, hogy int helyett egy intre mutató pointet veszünk át, és ahol eddig változó szerepelt, ott mechanikusan lecseréltük a változót (*pointer) jellegű kifejezésre. A amin függvényben természetesen a változó címét adjuk át:
/* a plusplus_plusplus függvény meghívása */
plusplus_plusplus(&a);
Miért oldja meg ez a problémánkat? Tekintsük az alábbi ábrát!
A paraméterátadás továbbra is érték szerinti: a pa paraméter és az a változó címe az inicializálást leszámítva továbbra is független. Jóllehet a mainbeli a változó címe lemásolódott, az még ugyanannak a változónak a címe. Vagyis a pa-n keresztül módosítjuk az átadott változót. Így az alábbi program kimenete 2.
#include<stdio.h>
void plusplus_plusplus(int*);
int main()
{
int a = 0;
/* a plusplus_plusplus függvény meghívása */
plusplus_plusplus(&a);
printf("%d\n",a);
return 0;}
void plusplus_plusplus(int* pa)
{
(*pa)=(*pa)+2;
}
Ezzel elértük azt, hogy a függvények nemcsak a visszatérési értéken keresztül adhatják vissza az eredményeiket, hanem pointerek segítségével is. Így ha több értéket szeretnénk visszaadni, akkor ez a módszer a megoldás. Erre jó példa a scanf függvény, és magyarázatot kaptunk arra is, hogy miért kell a változó elé írni a & jelet.
Összefoglaljuk az ismertetett paraméterátadás fontosabb lépéseit.
- A megváltoztatandó paraméter típusa helyett a függvény legyen a típusra mutató pointer
- A függvényben a változó helyett mechanikusan írjunk (*pointer)-t.
- A híváskor a megváltoztatni kívánt változó elé írjunk & jelet.
Fontos megértenünk, hogy a pointert itt a megváltoztathatóság miatt használtuk, ezeknél a pointer típusú paramétereknél a hívás helyén nem kell memóriát foglalnunk, pointert deklarálnunk: egyszerűen csak adjuk át egy változó címét.
Végezetül megjegyezzük, hogy a tömb típusú paraméterek esetén, az első elemre mutató pointert adja át a fordító, ezért a tömbelemek változtatása az eredeti (átadott) tömbelemeket is változtatja. Mivel a C-ben a sztringek is tömbök, ezért a fenti megjegyzés a sztringekre is érvényes.