****** Sbírka_úloh_z_jazyka_C ****** [UP Logo] Katedra informatiky Univerzity Palackého v_Olomouci ****** Práce s preprocesorem ****** * Číslice_dané_soustavy * Načtení_čísla_typu_int ***** Doplňující informace ***** Preprocesor zpracováná zdrojový text programu před použitím překladače. Nekontroluje syntaktickou správnost programu pouze provádí záměnu textů (např. symbolické jméno konstanty za její hodnotu). Řádky určené pro zpracování preprocessorem začínají znakem "#", za kterým by neměla být mezera. Makra bez parametru (konstanty) Definice konstanty obecně: #define jméno hodnota Příklady: #define PI 3.14 #define AND && #define ERROR printf("Chyba v programu!"); Při zpracování preprocesorem je každý výskyt jména konstanty v následujícím textu zdrojového souboru nahrazen hodnotou této konstanty. Vyjímku tvoří výskyty jmen konstant uzavřené v uvozovkách, které se nenahrazují (např. printf ("Logická spojka AND...");). Pokud je nutné změnit hodnotu konstanty je nutné ji nejprve zrušit a poté znova definovat. Příklad: #undef PI #define PI 3.1416 Pokud je potřeba definici konstatny zapsat na více než jeden řádek, zapíšeme na konci řádku znak "\", který preprocesor z hodnoty konstanty vynechá a pokračuje ve zpracovávání hodnoty na následujícím řádku. Příklad: #define DLOUHA_KONSTANTA 12345678.12345\ 67890123456 Makra s parametry Pokud v programu často používáme funkci, která je tvořena velmi malým počtem příkazů, bývá výpočet značně neefektivní, protože "administrativa" spojená s voláním funkce je výpočetně náročnější než samotné provedení příkazů v těle funkce. Místo klasické funkce lze použít makro s parametry, které nevytváří žádnou "administrativu" za běhu programu. Nevýhodou maker je naopak vznik delšího (většího) programu a nemožnost použití rekurze. Definice makra obecně: #define jméno(arg_1, ..., arg_N) tělo_makra kde arg_1 až arg_N jsou argumenty makra, které se chovají podobně jako parametry u funkcí. Upozorňujeme, že mezi jménem makra a závorkou nesmí být mezera. Příklad: #define na2(x) ((x)*(x)) Vzhledem k tomu, že při expanzi maker dochází pouze k nahrazení jednoho textu jiným, je doporučováno uzavřít celé tělo makra a také každý výskyt argumentu v těle makra do závorek. Příklady možných chyb: #define na2(x) x*x ... v = na2(f-g); /* prepise se na v = f-g*f-g; */ #define cti(c) c=getchar() ... if (cti(c)=='A'){... /* prepise se na if (c=getchar()=='A'){... */ Podmíněný překlad Podmíněný překlad (dále PP) používáme pro dočasné vynechání části zdrojového kódu při kompilaci. Typicky se PP používá pro vynechání ladících částí programu po jeho odladění, překlad platformově závislých části zdrojového kódu či dočasné odstranění (zakomentování) větší části kódu. PP řízený konstantním výrazem Syntaxe obecně: #if konstantní_výraz část_1 #else část_2 #endif Pokud je hodnota výrazu konstantní_výraz nenulová, překládá se část_1, jinak se překládá část_2. Části #else a část_2 lze vynechat. Příklad: #define WINDOWS 1 ... #if WINDOWS #define JMENO "C:\\Data\\input.txt" #else #define JMENO "/data/input.txt" #endif PP řízený definicí makra Syntaxe obecně: #ifdef jméno_makra část_1 #else část_2 #endif Pokud je makro jméno_makra definováno, překládá se část_1, jinak se překládá část_2. Opět platí, že části #else a část_2 lze vynechat. Příklad: #define WINDOWS #ifdef WINDOWS #define JMENO "C:\\Data\\input.txt" #else #define JMENO "/data/input.txt" #endif K dispozici je také direktiva ifndef, která provádí opak výše zmíněné direktivy ifdef. Syntaxe obecně: #ifndef jméno_makra část_1 #else část_2 #endif Pokud je makro jméno_makra definováno, překládá se část_2, jinak se překládá část_1. I zde platí, že části #else a část_2 lze vynechat. Příklad: #ifndef WINDOWS #define JMENO "/data/input.txt" #else #define JMENO "C:\\Data\\input.txt" #endif Další možnosti PP Direktivy ifdef a ifndef testují pouze existenci jediného makra, pro konsturkci složitějších podmínek lze použít operátor defined a logické operátory. Preprocesor také umožňuje složitější větvení PP pomocí direktivy elif, která má podobný význam jako else if v podmínkovém příkazu. Pro úplnost dodáváme, že direktiva error slouží pro výpis chyb již při zpracovaní preprocesorem. Příklad: #if defined(WINDOWS) && defined(DEBUG) #define LADENI 1 #elif !defined(DEBUG) #error Chyba nelze debugovat! #else #define LADENI 2 #endif =============================================================================== [Creative_Commons_License] Sbírka_úloh_z_jazyka_C. © Katedra_informatiky Univerzity_Palackého_v_Olomouci, 2009. Projekt byl vytvořen za podpory grantu FRVŠ 2061/2009/G1.