Učíme se C (23. díl) - Složité deklarace a definice - 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 (23. díl) - Složité deklarace a definice

22. března 2001, 00.00 | Orientujete se správně ve svém či cizím kódu? Říkáte si, že na deklaracích nemůže být nic složitého? Zkuste si sami správně přečíst některý z uváděných kódů! O tom jak správně číst složité deklarace a definice pojednává tento článek.

Složité deklarace a definice

Protože se v jazyce C můžeme setkat i s velmi složitými definicemi, či deklaracemi, měli bychom znát postup, jak tyto zápisy správně přečíst. Naštěstí to není nic složitého, a tak si celý algoritmus čtení složitějších definic jistě brzy osvojíte.

Celý postup se skládá z několika kroků. Tím prvním je nalezení identifikátoru proměnné nebo funkce. V některých případech může být i tento krok dosti složitý, ale většinou s tím nebudou potíže. Identifikátorem by mělo být slovo, které není klíčovým slovem, ani identifikátorem uživatelského typu a nevyskytuje se ani v seznamu formálních parametrů funkcí.

Poté co identifikátor nalezneme, postupujeme v dekódování definice směrem doprava. Při postupu tímto směrem můžeme narazit buď na uzavírací kulatou závorku, dvojici kulatých nebo hranatých závorek, nebo na znak středníku (popř. čárky), který deklaraci (definici) uzavírá. Pro jednotlivé případy se zachováme takto:

  • Narazíme-li na uzavírací kulatou závorku ')', obrátíme směr čtení. Od této chvíle tedy budeme definici číst směrem doleva. Při tom samozřejmě platí, že vše co jsme již dříve přečetli dále ignorujeme.
  • Dvojice kulatých závorek značí funkci. Mezi závorkami pak může být také seznam formálních parametrů funkce.
  • Dvojice hranatých závorek nepřekvapivě označuje pole. Závorky mohou obsahovat i údaj o velikosti pole.
  • Znak středníku (čárky) opět mění směr našeho dalšího postupu.

Při čtení ve směru zprava doleva můžeme narazit na otevírací kulatou závorku, znak '*', nebo na identifikátor datového typu.

  • Otevírací kulatá závorka '(' nás jednoduše otočí zpět do směru „zleva doprava“.
  • Znak '*' představuje, jak asi správně předpokládáte, ukazatel.
  • Identifikátor datového typu uvozuje celou definici (resp. deklaraci) a po jeho přečtení jsme s luštěním významu definice skončili. Napravo od datového typu by již neměly být žádné nepřečtené znaky. Nalevo od něj se mohou nalézat ještě případné modifikátory (např. static, volatile apod.)

Nyní můžeme snadno zkonstruovat slovní popis definovaného (deklarovaného) objektu. Celý proces si ukážeme na deklaraci funkce z minulého dílu tohoto seriálu. Deklarace vypadala takto:

double (*GetFunc(int n, double (*pfuncs[])(double)))(double);

Prvním krokem je nalézt identifikátor funkce. Tím je slovo GetFunc, takže větu popisující tuto funkci začneme slovy GetFunc je...“

V dalším kroku postupujeme směrem doprava, kde narazíme na otevírací kulatou závorku. V tomto směru může jít pouze o funkci, takže v jednom kroku přečteme vše až k odpovídající uzavírací závorce. Naši rozepsanou větu doplníme takto: „GetFunc je funkce se dvěma parametry, vracející...“ Protože definice druhého parametru funkce je opět dosti složitá, budeme ji, pro přehlednost, dekódovat zvlášť.

Nyní ale pokračujme ve čtení deklarace. Již přečtené části v dalších krocích samozřejmě neuvažujeme, zbývá tedy přečíst ještě tyto části:

double (*GetFunc(int n, double (*pfuncs[])(double)))(double);

Dalším přečteným znakem bude uzavírací kulatá závorka, která obrací směr čtení. Od této chvíle tedy čteme zprava doleva, čímž pádem narazíme na znak '*'. Naši větu tedy můžeme znovu rozšířit: „GetFunc je funkce se dvěma parametry, vracející ukazatel na...“

double (*GetFunc(int n, double (*pfuncs[])(double)))(double);

V dalším kroku narazíme znovu na otevírací kulatou závorku, která ale, při čtení zprava doleva, pouze obrací směr.

double (*GetFunc(int n, double (*pfuncs[])(double)))(double);

Při následujícím čtení narazíme opět na otevírací kulatou závorku, která tentokrát představuje funkci. Přečteme tedy vše až k odpovídající zavírací závorce a větu znovu rozšíříme: „GetFunc je funkce se dvěma parametry, vracející ukazatel na funkci s jedním parametrem typu double, vracející...“ Tentokrát jsme do věty zařadili i typ parametru funkce.

double (*GetFunc(int n, double (*pfuncs[])(double)))(double);

Nyní nás čeká už jen ukončovací středník, který obrátí směr čtení a identifikátor datového typu, díky kterému zakončíme námi konstruovaný popis: „GetFunc je funkce se dvěma parametry, vracející ukazatel na funkci s jedním parametrem typu double, vracející double.“ Kvůli lepší srozumitelnosti je možné výsledný popis ještě drobně stylisticky upravit.

Teď ještě rozluštíme definici druhého parametru funkce GetFunc(). Ta osamoceně vypadá takto:

double (*pfuncs[])(double)

Opět začneme u identifikátoru, kterým je slovo pfuncs, a řekneme: „pfuncs je...“

double (*pfuncs[])(double)

Dvojice závorek [] rozšíří naši větu o slova „...pole prvků typu...“

double (*pfuncs[])(double)

Po obrácení směru čtení uzavírací kulatou závorkou narazíme na znak '*' a k popisu tedy přidáme „...ukazatel na...”.

double (*pfuncs[])(double)

Další závorka nás znovu otočí, abychom znovu narazili na otevírací kulatou závorku, která, spolu s jí odpovídající uzavírací závorkou, značí funkci s jedním parametrem typu double. Přidáme tedy odpovídající zápis: „...funkci s parametrem typu double, která vrací...”

double (*pfuncs[])(double)

Konec definice znamená, stejně jako středník nebo čárka, obrácení směru čtení. To také provedeme, a následně přečteme zbytek definice, což je identifikátor typu. Stačí tedy přidat slovo „...double.“ a máme hotovo. Zjistili jsme tedy, že pfuncs je pole ukazatelů na funkce s parametrem double, které vrací double.

Pokud bychom při čtení definice narazili na situaci, kdy se nedají použít výše uvedená pravidla, jedná se o nesprávně zapsanou definici. Ale i pokud jsme při dekódování nenarazili na problém, není jisté, že je definice správně. Můžeme totiž napsat i sémanticky špatné definice, jako je například tato:

int x[20](char);

Celý zápis přečteme jako: „x je pole dvaceti prvků typu funkce s parametrem typu char, která vrací int.“ V C ovšem nelze definovat pole, jehož položkami jsou funkce. Podobných případů je více.

Asi nemusím dodávat, že postup, který jsme si zde tak důkladně procvičili, platí pro složité definice stejně, jako pro ty jednoduché, a že se dá použít i při konstrukci definic, či deklarací a ne jen pro jejich luštění.

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

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

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

 

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

Uživatelské jméno:

Heslo: