Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Učíme se C (22. díl) - Ukazatele na funkce
12. března 2001, 00.00 | Co to jsou ukazatele na funkce? Jak se definují, inicializují a jak
pomocí takovýchto ukazatelů volat jimi odkazované funkce vám objasní tento článek.
Ukazatele na funkce
Kromě klasických datových ukazatelů, s kterými jsme se doposud setkávali, nabízí jazyk C i ukazatele kódové. Ty ukazují na určitý úsek kódu (funkci) programu, který pak můžeme spustit nepřímo, právě pomocí těchto ukazatelů. Nejlépe si to ukážeme přímo na příkladu.
Definice ukazatele na funkci
Uvažujme, že máme nadefinovanou tuto funkci pro sčítání čísel double:
|
Tuto funkci můžeme volat normálně, jak jsme zvyklí, nebo si můžeme vytvořit ukazatel na ni a volat ji pomocí něho. Formální zápis definice takového pointeru vypadá takto:
typ (*identifikátor)(seznam_typů_parametrů)
Typem rozumíme datový typ, který vrací funkce, na kterou bude ukazovat náš pointer. Identifikátor je pak označením tohoto nového pointeru a v seznamu_typů_parametrů jsou, v odpovídajícím pořadí, uvedeny všechny typy parametrů odkazované funkce. Tento seznam sice můžeme nechat prázdný, ale kompilátor by v tomto případě neměl informace o typech parametrů funkce. Pokud bychom pak volali funkci, nepřímo přes ukazatel, se špatnými typy parametrů, mohlo by to vést ke špatné funkci programu. Proto se budeme držet bezpečnějšího způsobu a budeme typy parametrů uvádět.
Teď, když víme jak pointer na funkci nadefinovat, vytvoříme si ukazatel na výše uvedenou funkci secti().
double (*pf)(double, double);
Pointer pf teď může ukazovat na jakoukoliv funkci, která má dva parametry typu double a hodnotu typu double i vrací, tedy může ukazovat i na naši funkci secti(). Tento ukazatel je ale zatím neinicializovaný a pro volání funkce ho ještě nemůžeme použít. Jeho inicializaci provedeme prostým přiřazením identifikátoru existující funkce.
Inicializace kódového ukazatele
pf=secti;
Do proměnné pf byl uložen ukazatel na funkci secti(). Identifikátor přiřazované funkce se musí uvádět bez závorek se seznamem parametrů. Pokud vás zaráží, že jsme nemuseli použít operátor & pro získání adresy, je to proto, že kompilátor dokáže rozeznat, že chceme přiřadit ukazatel na funkci a ne funkci samotnou. Přiřadit proměnné přímo funkci totiž v C není možné. Pokud se vám ale více líbí zápis s operátorem reference, můžete využít i této (zcela ekvivalentní) možnosti:
pf=§i;
Ukazatel na funkci se dá inicializovat i jinými způsoby, podobně jako datový ukazatel. Můžeme tedy přiřazovat vzájemně kompatibilní ukazatele, inicializovat návratovou hodnotou funkce apod.
Volání funkce pomocí ukazatele
Jak už jsme si řekli, lze k volání funkce použít i ukazatele na tuto funkci. Zápis takového volání se řídí podle jednoho z následujících zápisů:
(*identifikátor_ukazatele)(seznam_skutečných parametrů);
nebo
identifikátor_ukazatele(seznam_skutečných parametrů);
Oba zápisy jsou funkčně ekvivalentní, a protože druhý (novější) z nich je jednodušší a bližší skutečnému zápisu volání funkce, budeme ho nadále používat.
Výše nadefinovaný a inicializovaný pointer pf bychom tedy pro zavolání jím odkazované funkce použili následujícím způsobem.
pf(15,4);
Výsledkem po vyhodnocení tohoto výrazu bude double hodnota 19.0, stejně jako kdybychom zavolali funkci secti(15,4);, na kterou pointer pf ukazuje.
Kódový ukazatel jako parametr funkce a její návratová hodnota
I kódový ukazatel můžeme bez problémů předat funkci jako její parametr, a to stejně, jako bychom to udělali s proměnnou jiného typu. Ani to není překvapivé, že funkce může kódový ukazatel i vracet. V následujícím, poněkud umělém, příkladu si nadefinujeme funkci GetFunc(), která za svůj parametr bere dokonce pole ukazatelů na funkce. V těle funkce se pak toto pole postupně prochází až do doby, kdy je nalezen první ukazatel, pro který jím odkazovaná funkce má v bodě 0 hodnotu 0. Tento ukazatel je pak funkcí vrácen.
Nejprve si nadefinujeme pole pfuncs ukazatelů na funkce, které rovnou inicializujeme některými funkcemi z math.h:
|
Jestli se vám předchozí definice zdála složitá, asi se zhrozíte při pohledu na hlavičku následující funkce. Pokud ji nebudete moci rozluštit, nelamte si s tím hlavu. Hned v příštím dílu tohoto seriálu si probereme postup, kterým dokážete přečíst libovolně složitou deklaraci (nebo definici). Zatím se ale spolehněte na výše uvedený popis toho, co funkce GetFunc() dělá. Pouze bych doplnil, že parametr n říká funkci GetFunc(), jak je pole pfuncs[] velké.
|
Obsah seriálu (více o seriálu):
- Učíme se C (1. díl)
- Učíme se C (2. díl)
- Učíme se C (3.díl)
- Učíme se C (4. díl)
- Učíme se C (5.díl)
- Učíme se C (6.díl)
- Učíme se C (7.díl)
- Učíme se C (8.díl)
- Učíme se C (9.díl) - Řetězce
- Učíme se C (10.díl) - Vstupně výstupní funkce
- Učíme se C (11.díl) - Formátovaný výstup
- Učíme se C (12.díl) - Formátový specifikátor
- Učíme se C (13.díl)
- Učíme se C (14.díl) - Vícerozměrná pole
- Učíme se C (15.díl) - Ukazatele
- Učíme se C (16.díl) - Modifikátory paměťové třídy
- Učíme se C (17.díl) - Pole a ukazatel
- Učíme se C (18. díl) - Dynamická alokace paměti
- Učíme se C (19. díl) - Práce se soubory I.
- Učíme se C (20. díl) - Práce se soubory II.
- Učíme se C (21. díl) - Parametry funkce main()
- Učíme se C (22. díl) - Ukazatele na funkce
- Učíme se C (23. díl) - Složité deklarace a definice
- Učíme se C (24. díl) - Funkce s proměnným počtem parametrů
- Učíme se C (25. díl) - Bitové operátory a bitové pole
- Učíme se C (26. díl) - Datové typy enum a union
- Učíme se C (27. díl - závěr) - Programové moduly
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007