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 36128×
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í
na
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
|
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 ...
|