4 FUNKCJE I STRUKTURA PROGRAMU
zostanie rozwinięte w wiersz printf(Mx/yM ” = %g\n’\ x/y);
w którym nastąpi sklejenie napisów, a więc w efekcie otrzymamy printf(”x/y = %g\n”, x/y);
Występujące w aktualnym argumencie wszystkie znaki cudzysłowu ” są zastępowane przez kombinację \”, a wszystkie znaki \ przez kombinację \\, toteż wynik jest po-prawną stałą napisową.
Operator preprocesora ## umożliwia sklejanie argumentów aktualnych podczas rozwijania makra. Jeśli w zastępującym tekście parametr sąsiaduje z operatorem ##,to ten parametr zastępuje się aktualnym argumentem, następnie usuwa operator ## wraz z otaczającymi go białymi znakami, a wynik przegląda ponownie. Oto przykład makra pastę sklejającego swoje dwa argumenty:
#define paste(front, back) front ## back /*sklej początek z końcem */
Wywołanie paste(name, 1) utworzy słowo namel.
Zasady zagnieżdżania operatora ## są tajemnicze; więcej szczegółów na ten tema można znaleźć w dodatku A.
Ćwiczenie 4.14. Napisz definicję makra swap(t,X,y) zamieniającego miejscami wartości argumentów x i y o typach t. (Skorzystaj ze struktury blokowej.)
Procesem tłumaczenia można sterować za pomocą instrukcji warunkowych, które są wykonywane w fazie preprocesora. Tym sposobem fragmenty kodu włącza si( do programu wybiórczo, w zależności od wartości warunków obliczanych podcza kompilacji. Jl
W wierszu zaczynającym się od #if oblicza się wartość stałego wyrażenia całkowitego (nie może zawierać sizeof, rzutowania ani stałych wyliczeń). Jeśli wyrażenie ma wartość różną od zera, to kolejne wiersze - aż do jednego z wierszy zaczynających się &
#endif, #elif lub #else - są włączane do programu. (Instrukcja preprocesora #elif P
# «•;
podobna do else if.) Wyrażenie defined(nazwa) w instrukcji #if jest równe 1 > J^5' nazwa została uprzednio zdefiniowana za pomocą #define; w przeciwnym przypal ma wartość 0.
Na przykład, aby zapewnić, że zawartość pliku nagłówkowego hdr.h jest wstawia^ do programu źródłowego tylko raz, zawartość tego pliku otacza się wyrażeniami " runkowymi preprocesora:
PREPROCESOR JĘZYKA C
powered by
#if! defined(HDR) #define HDR
/* zawartość pliku hdr.h jest tutaj */
#endif
pierwsze wstawienie pliku hdr.h definiuje nazwę HDR; przy każdej następnej próbie wstawienia tego pliku nazwa HDR jest już zdefiniowana, zawartość pliku jest więc omijana aż do wiersza zawierającego #endif. W podobny sposób można zapobiec wielokrotnemu wstawianiu różnych plików. Jeśli jest on stosowany konsekwentnie, to każdy nagłówek może sam sobie dołączać dowolne inne nagłówki, od których zależy jego zawartość; użytkownik tego nagłówka nie musi już się martwić o wzajemne zależności.
W następującym fragmencie programu sprawdza się wartość nazwy SYSTEM, by zadecydować, którą z wersji nagłówka należy wstawić do programu:
#if SYSTEM == SYSV #define HDR ”sysv.h"
#elif SYSTEM == BSD #define HDR ”bsd.h”
#elif SYSTEM == MSDOS #define HDR ”msdos.h”
#else
#define HDR ”defau!t.hM #endif
#include HDR
Do sprawdzenia, czy nazwa została uprzednio zdefiniowana, wprowadzono dwie specjalne instrukcje #ifdef oraz #ifndef. Pierwszy z przykładów, korzystający z #if, można więc napisać tak:
#ifndef HDR #define HDR
/* zawartość pliku hdr.h jest tutaj */
#endif
Język ANSI C