LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

> C/C++ (13) - Preprocesor podruhé

V dnešním dílu povídání o preprocesoru dokončíme. Probereme makra s parametry, standardní předdefinovaná makra a některé méně používané direktivy.

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

Makro s parametry

Minule jsem si ukázali, jak definovat jednoduché makro bez parametrů, nicméně podobně jako funkce i makro může mít parametry.

#define moje_gets(s, size) fgets((s), (size), stdin)

V dílu o standardním vstupu jsem haněl funkci gets a doporučoval místo ní fgets. Pokud programátora nebaví opisovat parametr stdin, může si pomoci výše uvedeným makrem. Je dobrým zvykem dávat parametry makra do závorek. Kdybychom třeba definovali makro pro násobení

#define KRAT(a, b) a * b
/*
Správně je
#define KRAT(a, b) ((a) * (b))
*/

Rozvine se při volání

KRAT(1 + 2, 3 + 4)

na

1 + 2 * 3 + 4

Občas se hodí makro pro menší ze dvou čísel. Zde pomůže ternární operátor.

#define MINIMUM(a, b) ((a) < (b) ? (a) : (b))

Zejména v souvislosti s makry se často vyskytuje také operátor zapomenutí, čárka.

Výraz x, y znamená nejprve vyhodnoť podvýraz x a hodnotu zapomeň, potom vyhodnoť podvýraz y a jeho hodnota bude výsledkem celého výrazu x, y. Celá konstrukce má smysl, pokud je na výrazu x podstatný jen jeho vedlejší efekt. Pokud nás například z ladících důvodu zajímá celkový počet volání putchar, můžeme jej volat prostřednictvím následujícího makra.

int pocet_volani = 0;

#define VOLEJ_PUTCHAR(c) (pocet_volani++, putchar((c)))

Je dobré si uvědomit, že takto definované makro umožňuje přístup i k návratové hodnotě volání putchar, což by definice pomocí dvou příkazů ukončených středníkem neumožňovala. V programu tedy můžeme makro volat i takhle.

int c = VOLEJ_PUTCHAR('A');
if (c == EOF) {
  puts("Chyba");
}

Parametry makra samozřejmě nemusejí být jen proměnné nebo výrazy.

#define PROHOD(typ, a, b) {typ c; c = a; a = b; b = c;}

Uvedené makro prohodí obsah dvou proměnných libovolného typu. Volalo by se například

int i = 1, j = 2;

PROHOD(int, i, j)

Rušení makra

Při běžném způsobu programování v C není obvykle třeba definici makra rušit. Výjimka může nastat, pokud chceme definovat makro jen pro použití v hlavičkovém souboru, ale nechceme, aby bylo platné i v souboru, který jej inkluduje. Také se může stát, že nám vadí makro z nějakého hlavičkového souboru, jehož obsah nemůžeme ovlivnit. Zde pomůže příkaz #undef

#undef MAKRO

/* nebo obecněji */

#ifdef MAKRO
#undef MAKRO
#endif

Drobnosti

Některé direktivy preprocesoru často neznají ani ostřílení C programátoři. Sem patří #, ## a #line. Pomocí # lze parametr makra po rozvinutí obalit uvozovkami a udělat z něj řetězcovou konstantu, ## zase spojuje 2 tokeny do jednoho identifikátoru.

#include <stdio.h>
#define PRINT_TOKEN(x) puts(#x)
#define PRINT_I(x) printf("%i\n", i##x)

int main(void) {

  int i1 = 7, i2 = 8, i3 = 9;

/* Pokud uhodnete, co vypíše PRINT_TOKEN(1 + 1); rozumíte preprocesoru */

  PRINT_TOKEN(1 + 1);
  PRINT_I(1); /* printf("%i\n", i1); */
  PRINT_I(2); /* printf("%i\n", i2); */
  PRINT_I(3); /* printf("%i\n", i3); */
  return 0;
}

O něco častěji se používá #pragma, tato direktiva má obvykle ještě parametr. Pokud mu překladač nerozumí, musí podle normy celou direktivu ignorovat. V opačném případě ji implementačně závislým způsobem zpracuje. Například pomocí #pragma warning( disable : 4507 ) můžeme v MS Visual C++ zakázat jedno konkrétní varovné hlášení při překladu kódu, který se zdá překladači podezřelý. Při použití jiného překladače (např. gcc), který tuto syntaxi direktivy #pragma nezná, nedojde k chybě, pouze bude celá direktiva ignorována.

Standardní makra

ANSI C definuje několik maker

  • __LINE__
    aktuální řádek ve zdrojovém souboru
  • __FILE__
    jméno zdrojového souboru
  • __TIME__
    čas překladu souboru
  • __DATE__
    datum překladu souboru
  • __TIMESTAMP__
    datum a čas modifikace souboru
  • __STDC__
    1, pokud překládáme jako ANSI C (a ne např. C++), jinak nedefinováno

Direktiva #line ovlivňuje předdefinovaná makra __LINE__ a __FILE__.

#line 174 "soubor.c"

Tato direktiva může být použita v generátorech C kódu z nějakého metazdrojáku, případná chybová hlášení (využívající __LINE__ a __FILE__) přeloženého vygenerovaného C kódu tak mohou být nastavena na původní metakód. Běžný programátor tedy #line asi nikdy nevyužije.

Příklad pro dnešní díl

Při vývoji větších projektů je dobrým zvykem umožnit logování událostí za běhu programu. V distribuční verzi může (ale nemusí) být žádoucí logování potlačit a logovací kód vůbec nepřekládat a nelinkovat do programu. V příkladu definuji makro ZALOGUJ, které se rozvine buď na prázdný řetězec, nebo na výpis logovací hlášky v závislosti na symbolu LOGOVAT. Všimněte si použití standardních maker __FILE__ a __LINE__.

/*
  gcc program.c -o program -DLOGOVAT
*/
#include <stdio.h>
#ifdef LOGOVAT
#define ZALOGUJ(s) printf("%s:%i %s\n", __FILE__, __LINE__, (s))
#else
#define ZALOGUJ(s)
#endif

int main(void) {
  ZALOGUJ("Začátek programu");
  return 0;
}

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

Příště se podíváme podrobněji na funkce. Postupně se také začneme zabývat projekty s větším počtem zdrojových souborů.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



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

28.11.2018 23:56 /František Kučera
Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

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

> Poslední diskuze

31.7.2023 14:13 / Linda Graham
iPhone Services

30.11.2022 9:32 / Kyle McDermott
Hosting download unavailable

13.12.2018 10:57 / Jan Mareš
Re: zavináč

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

Více ...

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