6. Ukazovatele a funkcie

6.3 Pointery na funkcie, funkcie ako parametre funkcií

V súvislosti s funkciami vždy hovoríme o ich návratových hodnotách. Pri riešení problémov využívame funkcie rôznych typov – používame napr. funkcie vracajúce char, int či double prípadne typ void. Spomeňte si na funkciu fopen, ktorá sa používa pri práci so súborom – je príkladom toho, že funkcie môžu vracať aj pointer na nejaký údajový typ (v tomto prípade na typ FILE).


Niekedy však s výhodou môžeme využiť aj možnosť deklarovať premennú ako pointer na funkciu vracajúcu nejaký typ. Znie to možno komplikovane, ale určite zaujímavo. Použitie pointera na funkciu umožňuje v jazyku C prenášať identifikátor funkcie ako parameter.

Deklarácia pointeru na funkciu má tvar: typ (*meno)();
 
kde typ je typ hodnoty, ktorú funkcia vracia a meno je identifikátor typu pointer na funkciu.


Všimnite si rozdiel medzi deklaráciami:
 
int *f1();
int (*f2)();

Prvá deklarácia určuje, že f1 je funkcia, ktorá vracia hodnotu typu pointer na int. Druhá definuje f2 ako pointer na funkciu, ktorá vracia hodnotu typu int.


Predpokladajme, že v programe používame funkciu, ktorej funkčný prototyp je takýto:
 
int sucet(int a, int b);
 
Ak máme deklarovanú premennú ako pointer na funkciu vracajúcu typ int napr. takto:
 
int (*p)();
 
tak môžeme napísať priradenie
 
p = sucet,
 
ktorým priradíme pointeru p adresu funkcie sucet. Pozor, ide síce o adresu funkcie, ale v tomto prípade operátor & už nie je potrebný! Funkciu sucet by sme teraz mohli zavolať aj takto:
 
s = (*p)(10, 20);


Použitie pointeru na funkciu si ukážeme na príklade:
 
Našou úlohou bude napísať program, ktorý vypíše tabuľku funkčných hodnôt dvoch polynomických funkcií: x * x + 1x * x * x - 2 * x v intervale ⟨−2, 2⟩ s krokom 0,1

#include <stdio.h>
#define A (-2)
#define B 2
#define KROK 0.1

double polynom1(double x);
double polynom2(double x);

void main(void)
{
	int i;
	double x;
	 /* pointer na funkciu, ktorá vracia double */
	double (*pf)();

	for (i = 0; i < 2; i++) {
		/* priradenie adresy funkcie */
		pf = (i == 0) ? polynom1: polynom2;
		for (x = A; x <= B; x += KROK) {
			printf("%12.5lf \t %12.5lf \n", x, (*pf)(x))
		}
	}
}

double polynom1(double x)
{
	return (x * x + 1);
}
double polynom2(double x)
{
	return (x * x * x - 2 * x);
}

V tomto prípade by bolo asi vhodnejšie napísať jednu funkciu tab nasledovne:

void tab(double a, double b, double k, double (*pf)())
{
	double x;

	for (x = a; x <= b; x += k) {
		printf("%12.5lf \t %12.5lf \n", x, (*p_fd)(x))
	}
}

Funkcia main by potom mohla vyzerať napr. takto:

void main(void) {
	tab(-2.0, 2.0, 0.1, polynom1);
	tab(-2.0, 2.0, 0.1, polynom2);
}

Pomocou pointerov na funkcie môžeme v programe „dynamicky“ reagovať na vzniknutú situáciu. Výhodne môžeme tento postup aplikovať všade tam, kde sa objavuje viacej funkcií rovnakého typu a s rovnakými parametrami líšiace sa len implementáciou. Typickým príkladom použitia pointeru na funkcie može byť zabezpečenie ovládania programu pomocou menu (pozri úlohu). Môžeme použiť pole pointerov na funkcie. Voľba používateľa, napr. stlačený kláves, má za následok vykonanie príslušnej funkcie.