Učíme se C (22. díl) - Ukazatele na funkce - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

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:

double secti(double a, double b)
{ return a+b;
}

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:

double (*pfuncs[4])(double)={cos,
                             sin,
                             log,
                             tan};

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é.

double (*GetFunc(int n, double (*pfuncs[])(double)))(double)
{ int i;
  for(i=0; i<n; i++)
   if (pfuncs[i](0.0)==0.0) return pfuncs[i];
  return NULL;
}

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

Diskuse k článku

 

Vložit nový příspěvek   Sbalit příspěvky

 

Zatím nebyl uložen žádný příspěvek, buďte první.

 

 

Vložit nový příspěvek

Jméno:

Pohlaví:

,

E-mail:

Předmět:

Příspěvek:

 

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: