Pred tým, ako sa váš program skompiluje, robí sa časť nazývaná preprocesing. V
tomto štádiu, sa dejú všeliaké podivnosti s riadkami, ktoré začínajú znakom
#. Týmto znakom sa píšu príkazy pre preprocesor.
Z jedným z takýchto príkazov sme sa už stretli, volá sa #include. Tento
príkaz nakopíruje do náško kódu obsah hlavičky knižnice — teda napr.
deklarácie funkcií (ako napr printf v cstdio, či cout v
iostreame), nie však definície, tie tam netreba. Pre nás tento príkaz
nemá nejaký hlbší význam.
Ďalším príkazom je #define. Tento príkaz sa dá použiť napríklad na
definovanie konštánt. Toto môže mať výhodu prehľadnejšieho kódu a zároveň, keď
sa rozhodneme zmeniť hodnotu, stačí nám zmeniť ju na jednom mieste. To čo
vyrobíme príkazom #define nazývame makro.
// preprocesor odstrani aj komentrare
#define MAXN 1047
#define INF 1023456789
#define eps 1e-8
int main(){
int A[MAXN];
for(int i = 0; i < MAXN; ++i)
A[i] = INF;
}
Tento program sa po preprocessingu zmení na
int main() {
int A[1047];
for (int i = 0; i < 1047; ++i)
A[i] = 1023456789;
}
a až potom sa kompiluje.
Príkaz #define vieme použiť aj na definíciu makier s parametrami. Tieto
nám takisto môžu zjednodušiť prácu. Treba si však dávať pozor pri práci s nimi,
ako uvidíme na príklade makier rozdiel1, rozdiel2 a
rozdiel3. Skôr než si pozriete zvyšok kódu, zamyslite sa, prečo sú makrá
rozdiel1 a rozdiel2 zlé.
#define rozdiel1(a, b) a - b
#define rozdiel2(a, b) (a - b)
#define rozdiel3(a, b) ((a) - (b))
// namiesto predoslych makier sa daju pouzit funkcie
// oproti funkciam ma makro vyhodu, ze funguje bez ohladu na typ premennej
// nasledovnu konstrukciu uz funkciou spravime len tazko
#define FOR(i, n) for (int i = 0; i < (n); ++i)
int main() {
int a = 0, b = 0, c = 0, d = 0;
// pre toto je makro rozdiel1 zle:
// namiesto (a-b)*c budeme mat a - b*c;
a = rozdiel1(a, b) * c;
// pre toto je makro rozdiel2 zle:
// namiesto a-(b+c) budeme mat a - b + c;
a = rozdiel2(a, b + c);
// konecne spravne makro:
a = rozdiel3(a, b + c) * d;
int celkovyrozdiel = 0;
FOR(i,n) FOR(j, n) {
celkovyrozdiel = rozdiel3(i, j);
}
// na zamyslenie: aka bude hodnota celkovyrozdiel teraz?
}
Posledné, čo si o preprocesingu ukážeme, sú ifdefy. Jednoducho sa vďaka
ním dajú vypínať kusy kódu. Napríklad vypínateľné debugovacie výpisy:
#include <iostream>
using namespace std;
// skus zakomentovat nasledujuci riadok, co sa zmeni?
#define DEBUG
#ifdef DEBUG
#define DBG(x) cout << #x << ": " << (x) << endl;
#else
#define DBG(x)
#endif
int main() {
int a = 7;
DBG(a);
DBG(a + 7);
}