Table of Contents

10 - Rekurzivní funkce, sdílené knihovny

Rekurzivní funkce

Při rekurzivním řešení výpočetního problému volá funkce seba sama, proto je důležité definovat ukončovací podmínku, kdy k volání už nedojde a naopak se vracíme z volaných funkcí. Typicky má funkce nějaký argument, který tak v podstatě hraje roli řídicí proměnné, podobně jako v cyklu.

Úkoly

Nápověda...

Nápověda...

Nápověda...

Poznámka...

Inspirujte se například příkladem z přednášky lec05.

Řešení...

Další úkoly na procvičení rekurze (na konec cvičení)

(Sdílené) knihovny

Motivační příklad: Fibonacciho posloupnost

Výpočet Fibonacciho posloupnosti je již jednou známý a dále neměnný. Nemá smysl jej pořád implementovat odznovu, proto jej chceme zařadit do knihovny, kterou budeme přepoužívat. Chceme, aby nám knihovna uměla vypočítat $n$-tý člen posloupnosti. Deklaraci (rozhraní) této funkcionality napíšeme do hlavičkového souboru fib.h:

int fib (int i);

Implementaci (definici) pak napíšeme do zdrojového souboru fib.c:

#include "fib.h"
int fib (int i){
  ... // TODO: Implement me :-)
}

Knihovnu pak můžeme použít v našem programu main.c, který spočítá třicáté Fibonacciho číslo:

int main (){
  return fib(30);
}

Nyní vše stačí zkompilovat. Knihovnu zkompilujeme s přepínačem -c, což vytvoří nespustitelný “object file” fib.o. Druhý příkaz zkompiluje soubor main.c a načte již hotový fib.o a “spojí” je dohromady do spustitelného souboru main.

gcc -c -o fib.o fib.c
gcc -o main main.c fib.o
./main
echo $?

Rozdělování kódu do menších kompilačních jednotek je také výhodné pro šetření času při kompilaci rozsáhlého projektu. Nástroje jako make, ninja nebo cmake slouží k organizaci kompilačních jednotek a kompilačních příkazů a zajištění, že se překompiluje vždy jen to, co je zrovna potřeba.

Sdílené knihovny: Porovnání efektivity implementací Fibonacciho posloupnosti

Inspirujte se například příkladem z přednášky lec07.

gcc -shared -fPIC -o libfibit.so fibit.c
gcc -shared -fPIC -o libfibrec.so fibrec.c

cp libfibrec.so libfib.so

gcc -o main -Wl,-rpath=. -L. -lfib

time seq 40 | main > fib_recursion.txt

cp libfibit.so libfib.so && time seq 40 | main > fib_interation.txt

Header Guards

Knihovnu lze samozřejmě používat v mnoha překladových jednotkách našeho projektu. Například funkce pro práci s textovými řetězci se budou používat často a na mnoha místech. Programátorům stačí znát deklaraci knihovních funkcí v hlavičkovém souboru. Problém může nastat, pokud se deklarace z hlavičkového souboru během preprocessingu “vloží” do zdrojového kódu na více míst. Demonstrujte:

int my_strlen(char*);

#ifndef HEADER_GUARD_MY_STRLEN_H
#define HEADER_GUARD_MY_STRLEN_H 1
int my_strlen(char*);
#endif