#if, #elif, #else i #endif — dyrektywy (C/C++)
Dyrektywa #if , z dyrektywami #elif, #else i #endif steruje kompilacją części pliku źródłowego..Jeśli wpisane wyrażenie (po #if) ma wartość różną od zera, grupa linii następująca bezpośrednio po dyrektywie #if jest zachowywana w jednostce translacyjnej.
Gramatyka
warunkowy :
część if części elifopcczęść elseopckoniec ifczęść if :
tekst z wierszem z operatorem ifwiersz z operatorem if :
#if wyrażenie stała#ifdef identyfikator
#ifndef identyfikator
części elif :
tekst linii eliftext części elif wiersza elif
Linia elif :
#elif wyrażenie stałainne części :
tekst linii elseelse linii :
#elseLinia endif :
#endif
Każdej #if dyrektywie w pliku źródłowym musi towarzyszyć dyrektywa #endif zamknięcia.Dowolna liczba #elif dyrektyw może pojawić się między #if i #endif dyrektyw, ale co najwyżej jedna #else dyrektywa jest dozwolone.Dyrektywa #else , jeśli jest obecna, musi być ostatnią dyrektywą przed #endif.
Dyrektywy #if, #elif, #else i #endif można zagnieździć w części tekstowej innych #if dyrektyw.Każda zagnieżdżona #else, #elif, lub #endif dyrektywa należy do najbliższej poprzedzającej #if dyrektywy.
Wszystkie dyrektywy kompilacji warunkowej, takie jak #if i #ifdef, muszą się zgadzać z zamknięciem #endif dyrektyw przed końcem pliku; w przeciwnym wypadku wygenerowany zostanie komunikat o błędzie.Kiedy dyrektywy kompilacji warunkowej są zawarte w plikach dołączonych, muszą spełniać te same warunki: muszą to być niedopasowane dyrektywy kompilacji warunkowej na kończy pliku dołączonego.
Wymiana makra jest wykonywana w części wiersza polecenia, który następuje po poleceniu #elif, więc wywołanie makra może zostać użyte w wyrażeniu stałym.
Preprocesor wybiera jedno z danych zdarzeń tekstu do dalszego przetwarzania.Określona w bloku text może być dowolną sekwencją tekstu.Może zajmować więcej niż jeden wiersz.Zwykle tekst to tekst programu, który ma znaczenie dla kompilatora lub preprocesora.
Preprocesor przetwarza wybrany tekst i przekazuje go do kompilatora.Jeśli tekst zawiera dyrektywy preprocesora, preprocesor wykonuje te dyrektywy.Tylko bloki tekstu wybrane przez preprocesor są kompilowane.
Preprocesor wybiera pojedynczy tekstowy element oceniając wyrażenie stałej następujące po każdym #if lub dyrektywie #elif do czasu, gdy odnajdzie prawdziwe (niezerowe) wyrażenie stałej.To powoduje zaznaczenie całego tekstu (włączając inne dyrektywy preprocesora, począwszy od #) do związanych z nią #elif, #else lub #endif.
Jeśli wszystkie wystąpienia constant-expression są fałszywe lub jeśli nie pojawi się dyrektywa #elif, preprocesor wybiera blok tekstu po klauzuli #else.Jeśli klauzula #else zostanie pominięta, a wszystkie wystąpienia wyrażenia stałego w bloku #if są fałszywe, nie zostanie zaznaczony żaden blok tekstu.
Wyrażenie stałe jest wyrażeniem liczby całkowitej z następującymi ograniczeniami dodatkowymi:
Wyrażenia muszą mieć typ całkowity i mogą obejmować tylko stałe będące liczbami całkowitymi, stałe znaków i zdefiniowane operatory.
Wyrażenie nie może używać sizeof ani operatora typu rzutowania.
Środowisko docelowe może nie być w stanie odtworzyć wszystkich zakresów liczb całkowitych.
Tłumaczenie reprezentuje typ int taki sam jak typ długi i unsigned int taki sam jak unsigned long.
Tłumacz może przetłumaczyć stałe znaków na zestaw wartości kodu inny od zestawy środowiska docelowego.Aby określić właściwości środowiska docelowego, sprawdź wartości makr z LIMITS.H w kompilacji aplikacji dla środowiska docelowego.
Wyrażenie nie musi wykonywać żadnych zapytań środowiska i musi być izolowane od szczegółów implementacji na komputerze docelowym.
Operator preprocesora zdefiniowany może być wykorzystany w specjalnym wyrażeniu stałym, jak pokazano w następującej składni:
zdenifiniowano( identifier )
zdefiniowano identifier
To wyrażenie stałe jest uważane za prawdziwe (inne od zera), jeżeli identyfikator jest obecnie zdefiniowany; w innym wypadku warunek jest fałszywy (0).Identyfikator zdefiniowany jako pusty tekst jest uważany za zdefiniowany.Zdefiniowana dyrektywa może być używana w #if i w dyrektywie #elif , nigdzie indziej.
W poniższym przykładzie dyrektywy #if i #endif kontrolują kompilację jednego z trzech wywołań funkcji:
#if defined(CREDIT)
credit();
#elif defined(DEBIT)
debit();
#else
printerror();
#endif
Wywołanie funkcji do credit jest skompilowane, jeśli identyfikator CREDIT zostanie zdefiniowany.Jeśli identyfikator DEBIT został zdefiniowany, wywołanie funkcji debit jest skompilowane.Jeśli żaden identyfikator nie został zdefiniowany, jest kompilowane wywołanie printerror.Należy zauważyć, że CREDIT i credit są różnymi identyfikatorami w C i C++, ponieważ ich przypadki są różne.
Instrukcje kompilacji warunkowej w poniższym przykładzie zakładają wcześniej zdefiniowaną symboliczne stałą o nazwie DLEVEL.
#if DLEVEL > 5
#define SIGNAL 1
#if STACKUSE == 1
#define STACK 200
#else
#define STACK 100
#endif
#else
#define SIGNAL 0
#if STACKUSE == 1
#define STACK 100
#else
#define STACK 50
#endif
#endif
#if DLEVEL == 0
#define STACK 0
#elif DLEVEL == 1
#define STACK 100
#elif DLEVEL > 5
display( debugptr );
#else
#define STACK 200
#endif
Pierwszy blok #if zawiera dwa zestawy zagnieżdżonych dyrektyw #if, #else i #endif.Pierwszy zestaw dyrektyw jest przetwarzany tylko wtedy, gdy DLEVEL > 5 jest true.W przeciwnym razie instrukcje po #innego są przetwarzane.
Dyrektywy #elif i #else w drugim przykładzie są wykorzystywane do wytwarzania jednego z czterech wyborów, na podstawie wartości z DLEVEL.Stała STACK jest równa 0, 100 lub 200, w zależności od definicji DLEVEL.Jeśli DLEVEL jest większe niż 5, instrukcja
#elif DLEVEL > 5
display(debugptr);
jest skompilowany i STACK nie jest zdefiniowany.
Typowym zastosowaniem dla kompilacji warunkowej jest zapobieganie wielu dołączeniom tego samego pliku nagłówka.W języku programowania C++, w którym klasy często są zdefiniowane w plikach nagłówkowych, następujące konstrukcje mogą zostać wykorzystane do zapobieżenia wielu definicjom:
/* EXAMPLE.H - Example header file */
#if !defined( EXAMPLE_H )
#define EXAMPLE_H
class Example
{
...
};
#endif // !defined( EXAMPLE_H )
Poprzedzający kod sprawdza, czy symboliczna stała EXAMPLE_H jest zdefiniowana.Jeśli tak, plik został już włączony i nie musi być ponownie przetwarzany.Jeśli nie, stała EXAMPLE_H jest definiowana, aby oznaczyć EXAMPLE.H jako już przetworzone.