na obsah klávesové zkratky na hlavní stránku na menu

Funkce

Funkce jsou stavebním kamenem jazyka C. V tomto článku se seznámíme se základem práce s funkcemi.

Deklarace funkce

V deklaraci funkce musíme určit, jak se bude funkce chovat navenek. Musíme určit jméno funkce, vstupní parametry a návratovou hodnotu.

int secti (int a, int b)
{
  return a + b;
  printf("%d", a + b); // neprovede se
}

// ...

int c = secti(2, 3); // volání funkce, v proměnné c bude 5

Ve výpisu kódu jsme definovali funkci. Jak vidíme, na rozdíl od Pascalu v jazyce C není vyhrazené klíčové slovo pro funkci. Hlavička funkce se skládá pouze z návratového typu, jména a seznamu parametrů oddělených čárkami v kulatých závorkách. Zde tedy máme funkci secti (jména smějí obsahovat pouze alfanumerické znaky, podtržítka a první znak nesmí být číslice), která vrací celočíselnou hodnotu a přebírá celkem dva parametry typu int, které jsme pojmenovali a a b. Jelikož jsme vytvořili funkci, která má vracet hodnotu, musíme zajistit její vyplnění. Zavoláním return okamžitě ukončíme provádění funkce a vrátíme výsledek výrazu zapsaný za ním. printf() se tedy nikdy neprovede.

V jazyce Pascal existovalo speciální označení pro funkci, která nic nevracela – procedura. Toto označení se v jazyce C nepoužívá, pouze označíme, že je návratový typ prázdný. K tomu je určen speciální typ void. Tento typ značí prázdnou hodnotu, hodnotu bez typu. Procedura v jazyce C tedy vypadá následovně:

void vypis_hello (void)
{
  printf("hello world\n");
  return; // není nutné
}

// ...

vypis_hello();

Vytvořili jsme funkci, která nic nevrací, nebo-li proceduru. Pokud někdy potřebujeme ukončit vykonávání procedury předčasně, zavoláme return bez výrazu. V našem příkladu toto není nutné, protože procedura stejně končí. Za povšimnutí stojí také to, že i když funkce nepřejímá žádné parametry, musíme napsat kulaté závorky. Uvnitř závorek by mělo být podle standardu buď void, nebo nic. Standard C99 povoluje jen první možnost. Pokud voláme proceduru, musíme též napsat za název kulaté závorky. Pokud je vynecháme, funkce se nezavolá, ale překladač nás neupozorní. V sekci ukazatele si vysvětlíme proč.

Rekurze

V jazyce C lze bez problému využít rekurzi. Stačí pouze zavolat funkci samu v sobě. Je samozřejmě na nás, abychom zajistili konečnost takového zápisu.

void vypis_radu (int cislo)
{
  if (cislo < 0) return;
  printf("%d\n", cislo);
  vypis_radu(cislo - 1);
}

// ...

vypis_radu(10);

Tento kód vypíše velmi neobratně čísla od deseti do nuly. Rekurze má typicky ukončovací podmínku, v tomto případě je to test zápornosti předaného parametru. Na řádce pět voláme v těle funkce tuto funkci znovu s jiným parametrem. V tuto chvíli se vyhodnocování původní funkce přeruší, vykoná se vnořená funkce a poté se vykonávání vnější funkce obnoví. Tento kód stejně jako většina ostatních případů rekurze, lze mnohem efektivněji přepsat za pomoci cyklu. Zde je uveden pro ilustraci.

Funkce main()

Už v prvním programu jsme potřebovali funkci main(). Tato funkce je vstupním bodem programu, proto musí být v každém programu právě jednou! Její hlavička je poměrně komplikovaná, její účel je ale zřejmý.

int main (int argc, char **argv)
int main (void)

Dříve jsme se setkali jen s prvním typem hlavičky. Toto je tzv. plná definice funkce main(). Konzolové aplikace, jako je např. překladač GCC, mohou měnit svoje chování v závislosti na předaných parametrech příkazové řádky. Tyto parametry pak program obdrží právě ve dvou parametrech funkce main(). První parametr říká, kolik celkem parametrů jsme obdrželi, druhý parametr je seznam řetězců, ve kterém jsou postupně uložené všechny parametry. V případě, že nemáme o tyto parametry zájem, můžeme využít druhou formu zápisu.

Návratová hodnota funkce main() představuje možnost, jak oznámit terminálu, že program skončil v pořádku, či s chybou. Standardně je hodnota EXIT_SUCCESS (definovaná v souboru stdlib.h většinou jako nula) považována za signalizaci správného ukončení programu. V případě předání EXIT_FAILURE došlo při běhu programu k chybě.

#include <stdio.h>

int main (int argc, char **argv)
{
  int i;
  for (i = 0; i < argc; i++)
  {
    puts(argv[i]);
  }
  return 0;
}

Tento program vypíše všechny předané parametry. Máme-li program přeložen pod jménem parametry a zavoláme ho z terminálu v následující podobě

./parametry parametr1 --parametr2 par3

obdržíme výpis

./parametry
parametr1
--parametr2
par3

Všimněme si, že první parametr není parametr1, ale ./parametry, tedy forma, jakou spouštíme program. To se může někdy hodit. První skutečný parametr má tedy index jedna a ne nula, jak bychom očekávali. Parametry se nijak neupravují a předávají se s pomlčkami i jiným formátováním. Terminál je pouze rozseká podle mezer mezi nimi. Je na programátorovi, aby si parametry sám zpracoval.