LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> C/C++ (15) - Proměnné

V dnešním díle probereme podrobněji proměnné. Ukážeme si, jak se definují ukazatele na funkce a na co jsou dobré. Dojde na modifikátory proměnných a to i v souvislosti s projekty z více souborů.

23.2.2005 15:00 | Jan Němec | Články autora | přečteno 39683×

Funkce jako typ a proměnná

Funkci již umíme definovat a volat, umíme také deklarovat jejich hlavičky. Céčko navíc umožňuje definovat ukazatel na funkci. Jedná se skutečně o ukazatel do paměti, označuje místo v kódu, kde začíná přeložená funkce. S ukazatelem na funkci lze pracovat jako s běžnou proměnnou, můžeme do něj přiřadit nějakou hodnotu nebo jej předat jako parametr funkce, lze také vypsat jeho hodnotu. Pokud architektura umožňuje číst programu vlastní kód (běžně ano), můžeme ukazatel na funkci přetypovat na ukazatel na unsigned char a naučit se strojový kód. Pamětníci z dob MS-DOSu zavzpomínají i na sebemodifikaci spuštěného kódu, ale v chráněném módu na Linuxu podobné pokusy skončí špatně. Především však lze funkci, na niž ukazatel míří zavolat.

/* p je ukazatel na funkci s parametrem typu const char *
   a vracející int */
int (* p)(const char *);

/* Identifikátor funkce bez kulatých závorek znamená
   ukazatel na funkci */
p = puts;
printf("Funkce puts je v paměti na adrese %p.\n", (void *) p);
/* Ukazatel na puts lze normálně zavolat */
p("Ahoj světe!");

Nejsložitější na celém příkladu je určitě konstrukce typu ukazatele. Nejdřív se píše typ návratové hodnoty funkce, potom v kulatých závorkách hvězdička a identifikátor - jméno definovaného ukazatele a nakonec následují opět v kulatých závorkách typy parametrů funkce. Všimněte si, že název funkce je v C kódu pouze konstantní ukazatel na tuto funkci. Volání funkce přes ukazatel, definovaný jako proměnná, je už stejné, jako běžné volání funkce.

Ukazatele na funkce se nejčastěji používají v souvislosti s knihovnami, kdy je třeba nějakým dostatečně obecným způsobem parametrizovat algoritmus z knihovny. Pomocí ukazatele na funkci lze říci nějaké GUI knihovně, co se má stát při stisknutí tlačítka (zavolat uživatelskou funkci předanou jako parametr). Časově náročné funkce z knihoven občas umožní zadat jako parametr funkci, která se bude jednou za čas během výpočtu volat. Například programátor obecně užitečné knihovny na násobení velkých matic neví, jakým způsobem (a zda vůbec) informovat uživatele během výpočtu. To ví až aplikační programátor. Proto programátor knihovny přidá jako poslední parametr funkce na násobení matic ukazatel na funkci (tu už píše aplikační programátor), která se zavolá po vypočtení každého prvku výsledné matice. V grafické aplikaci se pak může pohybovat teploměr od 0% ke 100%, v interaktivním konzolovém programu se bude vypisovat na standardní výstup atd., ačkoli oba programy používají stejnou knihovnu.

#include <stdio.h>
/* Tohle je jako časově náročná funkce z knihovny */
void NapisStoTecek(void (* callback)(int)) {
  int i;

  for (i = 0; i < 100; i++) {
    /* Jednou za deset teček zavolej parametr */
    if (!(i % 10)) callback(i);
    /* Vypisuj tečky */
    putchar('.');
  }
}

/* Funkce volaná z knihovny, ale definovaná v aplikačním kódu */
void parametr(int procent) {
  printf("\nHotovo na %i%%\n", procent);
}

/* Hlavní program */
int main(void) {
  NapisStoTecek(parametr);
  return 0;
}

Modifikátory proměnných

Když nepočítáme parametry funkcí, zná Céčko dva druhy proměnných. Lokální, definované uvnitř funkce, a globální definované mimo funkci. Lokální proměnná má vyhrazené místo na zásobníku, a je tedy svázána nejen s konkrétní funkcí, ale přímo s její instancí. V případě rekurze tak pro každé volání funkce vzniknou i instance jejích lokálních proměnných a přiřazení do lokální proměnné proto ovlivní hodnotu pouze příslušné instance. Toto chování lze změnit klíčovým slovem static. Lokální proměnná definovaná jako static má vždy jen jednu instanci uloženou stejně jako globální proměnné, navíc její případná inicializace v definici proběhne jen jednou.

void funkce(void) {
  static int i = 0;

  printf("Celkový počet volání funkce = %i\n", ++i);
}

U globálních proměnných má static poněkud jiný význam. Jedná se o omezení platnosti proměnné na příslušný modul. Z ostatních souborů je pak tato proměnná nedostupná, jde tedy o jakousi ochranu identifikátorů podobně jako v případě static funkcí.

Globální proměnná z jiného zdrojového souboru se zpřístupní pomocí extern. Pokud v jednom souboru definujeme

int pocet;

můžeme tuto proměnnou používat z jiného souboru, pokud v něm deklarujeme

extern int pocet;

Jde tedy jen (podobně jako v případě hlaviček funkcí) o jakousi informaci pro překladač, že pocet je známý identifikátor, proměnná typu int, která je definovaná někde jinde. Pokud v celém projektu není nikde definovaná bez extern, ale je používaná, projde vlastní překlad jednotlivých souborů, ale při linkování dojde k chybě.

Pokud nám záleží na efektivitě programu, můžeme označit lokální proměnnou jako register.

void funkce(void) {
  register int i;
  /* ... */
}

Je to doporučení pro překladač, aby umístil tuto proměnnou do registru procesoru a nikoli na zásobník. Práce s registry je pochopitelně podstatně rychlejší. Překladač může toto doporučení ignorovat (u dnešních překladačů běžné) a může také proměnnou dát do registru sám od sebe (i to je obvyklé). Označení register má tedy smysl pro dobrovolně spolupracující překladače se špatnou optimalizací, například staré dosovské verze Borland C++.

Překladač se obvykle pokouší kód zjednodušit tak, aby na cílovém procesoru běžel co nejrychleji. V tom mu podstatně pomáhá znalost hodnot proměnných, například po

i = 5;

může předpokládat, že v proměnné i bude skutečně hodnota 5 a to až do nějakého příkazu, který to může změnit. Problém nastane u programů s obsluhou asynchronních událostí (signály) nebo více vlákny. Cyklus

int i = 0;

while (!i);

tj. čekej, dokud signál nebo jiné vlákno nezmění hodnotu i, smí překladač "vyoptimalizovat" na

while (1);

tj. čekej do nekonečna. Z tohoto důvodu existuje modifikátor volatile, který překladači zakazuje provádět jakékoli předpoklady o hodnotě proměnné.

volatile int i = 0;

while (!i);

Teď je příklad správný, pouze poněkud neefektivní, neboť aktivní čekání zbytečně vytíží procesor.

Modifikátor const již známe. Jde o označení proměnných, které nelze jednoduchým způsobem měnit. Nejedná se však o skutečné konstanty, neboť je nelze použít např. při definici mezí polí. Tento modifikátor je rozumné použít zejména u vstupních parametrů funkce předávaných pomocí ukazatelů. Je-li parametrem funkce const char *, je zřejmé, že funkce nemá v úmyslu řetězec měnit. Užití const tak zvyšuje čitelnost programu.

Pokračování příště

V příštím dílu se naučíme psát hlavičkové soubory.

Verze pro tisk

pridej.cz

 

DISKUZE

Pokračování......... ??? 4.3.2005 11:43 Herfik
  L Re: Pokračování......... ??? 4.3.2005 15:45 Jan Němec




Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

14.11.2017 16:56 /František Kučera

Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).


Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

13.9.2017 8:00 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

27.7.2017 12:24 / Jaromir Obr
Cteni/zapis

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze