C++: Dyrektywy preprocesora
Dyrektywa #include ma jedną z 2 postaci: #define <nazwa_pliku>
lub
#define "nazwa_pliku"
Dyrektywa #include służy do włączania pliku o podanej nazwie do kompilowanego programu.
Do tworzenia makrodefinicji służy dyrektywa #define. Składnia: #define identyfikator ciąg_symboli
lub
#define identyfikator(id1, id2, ...) ciąg_symboli
Pierwsza postać zleca preprocesorowi zastąpienie każdego wystąpienia identyfikatora wskazanym ciągiem_symboli. Spacje rozpoczynające i kończące ciąg_symboli są usuwane. Przykład: #define WIERSZY 10 #define KOLUMN 5 ... int tablica[WIERSZY][KOLUMN];deklaracja tablicy tablica zostanie zamieniona w następujący sposób: int tablica[10][5];
Druga postać dyrektywy #define służy do definicji tzw. makra funkcyjnego. W tej dyrektywie pomiędzy identyfikatorem i nawiasem otwierającym ( nie może być spacji. W programie każde wystąpienie identyfikatora, po którym następuje nawias oraz ciągi identyfikatorów oddzielone przecinkami i zakończone nawiasem zamykającym są traktowane jako makrodefinicje. Makrodefinicje zastępuje się ciągiem_symboli podanym w makrodefinicji. Spacje rozpoczynające i kończące ciąg_symboli są usuwane. W podanym ciągu każde wystąpienie identyfikatora z listy parametrów (id1, id2, ...) zastępuje się parametrami aktualnego makrowywołania. Liczba parametrów w makrodefinicji musi być taka sama, jak w makrowywołaniu. Przykład: #define MIN(x, y) (((x) < (y)) ? (x) : (y)) ... a = MIN(i, j);przypisanie zostanie zastąpione przez: a = (((i) < (j)) ? (i) : (j); Przy definiowaniu makrodefinicji funkcyjnych należy wszystkie argumenty ujmować w nawiasy - makrodefinicje są rozwijane tekstowo przez preprocesor, co może powodować nieoczekiwaną zmianę znaczenia pewnych zapisów, jak np.: #define SQR(x) x*x ... res = SQR(a+4);spowoduje rozwinięcie do postaci: res = a+4*a+4;podczas, gdy my byśmy oczekiwali, że otrzymamy wyrażenie: res = (a+4)*(a+4); Uwagi:
Dyrektywa #undef służy do unieważniania wcześniej zdefiniowanego makra. Składnia: #undef identyfikator
Jeżeli istnieje konieczność warunkowej kompilacji fragmentów programu, to możemy do tego celu użyć jednej z poniższych składni: #if defined(nazwa)
lub
... // kod programu kompilowany, gdy zdefiniowano symbol nazwa [ #elif defined (nazwa1) ] ... // kod programu kompilowany, gdy zdefiniowano symbol nazwa1 [ #else ] ... // kod programu kompilowany, gdy nie zdefiniowano symboli nazwa ani nazwa1 #endif #ifdef nazwa
lub
... // kod programu kompilowany, gdy zdefiniowano symbol nazwa [ #else ] ... // kod programu kompilowany, gdy nie zdefiniowano symbolu nazwa #endif #ifndef nazwa
... // kod programu kompilowany, gdy nie zdefiniowano symbolu nazwa [ #else ] ... // kod programu kompilowany, gdy zdefiniowano symbol nazwa #endif Dyrektywy #elif i #else są we wszystkich przypadkach opcjonalne.
Przykłady: Różny sposób znalezienia minimalnej wartości w zależności od tego, czy zdefiniowano symbol MIN, czy nie: #ifdef MIN a = MIN(i, j); #else a = (i < j) ? (i) : (j); #endifW zależności od zdefiniowanego symbolu dołączane są różne pliki nagłówkowe do obsługi grafiki: #if defined(MSC) #include <graph.h> #elif defined(TURBOC) #include <graphics.h> #endiPewne makra są zdefiniowane przez kompilator i mogą być używane podczas kompilacji:
|