direktivy #if, #elif, #else a #endif (C/C++)

Direktiva #if s direktivami #elif, #else a #endif řídí kompilaci částí zdrojového souboru. Pokud má zapsaný výraz (za #if) nenulovou hodnotu, skupina řádků bezprostředně za direktivou #if zůstane v jednotce překladu.

Gramatika

podmíněné :
if-part elif-partsoptelse-partoptendif-line

if-part :
if-line text

if-line :
#ifvýraz konstanty
identifikátor #ifdef
identifikátor #ifndef

elif-parts :
elif-line text
elif-parts elif-line text

elif-line :
#elifvýraz konstanty

else-part :
text jiného řádku

else-line :
#else

endif-line :
#endif

Poznámky

Každá direktiva #if ve zdrojovém souboru musí odpovídat uzavírací direktivě #endif . Mezi direktivou #if a #endif se může objevit libovolný počet direktiv #elif, ale nejvýše jedna direktiva #else je povolena. Direktiva #else, pokud existuje, musí být poslední direktivou před #endif.

Direktivy #if, #elif, #else a #endif mohou vnořit do textových částí jiných direktiv #if. Každá vnořená direktiva #else, #elif nebo #endif patří k nejbližší předchozí direktivě #if .

Všechny direktivy podmíněné kompilace, například #if a #ifdef, musí odpovídat uzavírací direktivě #endif před koncem souboru. V opačném případě se vygeneruje chybová zpráva. Pokud jsou direktivy podmíněné kompilace obsaženy v souborech zahrnutí, musí splňovat stejné podmínky: Na konci souboru zahrnutí nesmí být žádné direktivy podmíněné kompilace.

Nahrazení makra se provádí v rámci části řádku, která následuje za příkazem #elif , takže volání makra lze použít ve výrazu konstanty.

Preprocesor vybere jeden z daných výskytů textu pro další zpracování. Blok zadaný v textu může být libovolná posloupnost textu. Může zabírat více než jeden řádek. Text je obvykle text programu, který má význam pro kompilátor nebo preprocesor.

Preprocesor zpracuje vybraný text a předá ho kompilátoru. Pokud text obsahuje direktivy preprocesoru, provede preprocesor tyto direktivy. Kompilují se pouze textové bloky vybrané preprocesorem.

Preprocesor vybere jednu textovou položku tak, že vyhodnotí konstantní výraz následující za každou #if nebo #elif direktivu, dokud nenajde pravdivý (nenulový) konstantní výraz. Vybere veškerý text (včetně jiných direktiv preprocesoru začínající #na ) až po přidružené #elif, #else nebo #endif.

Pokud jsou všechny výskyty konstanty výrazu false nebo pokud se nezobrazí žádné direktivy #elif , preprocesor vybere blok textu za klauzulí #else . Pokud není k dispozici žádná #else klauzule a všechny instance konstantního výrazu v bloku #if mají hodnotu false, nebude vybrán žádný blok textu.

Výraz konstanty je celočíselný konstantní výraz s těmito dodatečnými omezeními:

  • Výrazy musí mít celočíselný typ a mohou obsahovat pouze celočíselné konstanty, znakové konstanty a definovaný operátor.

  • Výraz nemůže použít sizeof operátor přetypování typu nebo .

  • Cílové prostředí nemusí představovat všechny rozsahy celých čísel.

  • Překlad představuje typ int stejným způsobem jako typ longa unsigned int stejným způsobem jako unsigned long.

  • Překladatel může přeložit znakové konstanty na sadu hodnot kódu, které se liší od sady pro cílové prostředí. Pokud chcete určit vlastnosti cílového prostředí, pomocí aplikace vytvořené pro toto prostředí zkontrolujte hodnoty OMEZENÍ. Makra H .

  • Výraz nesmí dotazovat prostředí a musí zůstat izolovaný od podrobností implementace v cílovém počítači.

Operátory preprocesoru

definováno

Definovaný operátor preprocesoru lze použít ve speciálních konstantních výrazech, jak ukazuje následující syntaxe:

defined(identifikátor)
definovanýidentifikátor

Tento konstantní výraz se považuje za pravdivý (nenulový), pokud je identifikátor aktuálně definovaný. V opačném případě je podmínka false (0). Identifikátor definovaný jako prázdný text se považuje za definovaný. Definovaný operátor lze použít v #if a #elif direktivě, ale nikde jinde.

V následujícím příkladu #if a direktivy #endif řídí kompilaci jednoho ze tří volání funkce:

#if defined(CREDIT)
    credit();
#elif defined(DEBIT)
    debit();
#else
    printerror();
#endif

Volání funkce se credit zkompiluje, pokud je identifikátor CREDIT definován. Pokud je identifikátor DEBIT definovaný, volání funkce se debit zkompiluje. Pokud není definován ani jeden identifikátor, je volání printerror zkompilováno. credit I CREDIT jsou jedinečné identifikátory v jazyce C a C++, protože jejich případy se liší.

Příkazy podmíněné kompilace v následujícím příkladu předpokládají dříve definovanou symbolickou konstantu s názvem 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

První blok #if zobrazuje dvě sady vnořených #if, #else a direktiv #endif . První sada direktiv je zpracována pouze v případě, že DLEVEL > 5 má hodnotu true. V opačném případě se příkazy po #else zpracují.

Direktivy #elif a #else v druhém příkladu slouží k provedení jedné ze čtyř možností na základě hodnoty DLEVEL. Konstanta STACK se nastaví na 0, 100 nebo 200 v závislosti na definici .DLEVEL Pokud DLEVEL je větší než 5, příkaz

#elif DLEVEL > 5
display(debugptr);

je zkompilovaný a STACK není definován.

Běžným použitím podmíněné kompilace je zabránění vícenásobnému zahrnutí stejného souboru hlaviček. V jazyce C++, kde jsou třídy často definovány v souborech hlaviček, lze konstruktorům, jako je tato, zabránit více definic:

/*  EXAMPLE.H - Example header file  */
#if !defined( EXAMPLE_H )
#define EXAMPLE_H

class Example
{
    //...
};

#endif // !defined( EXAMPLE_H )

Předchozí kód zkontroluje, jestli je definovaná symbolická konstanta EXAMPLE_H . Pokud ano, soubor už je zahrnutý a není potřeba ho znovu zpracovat. Pokud ne, konstanta EXAMPLE_H je definována pro označení EXAMPLE. H tak, jak je již zpracováno.

__has_include

Visual Studio 2017 verze 15.3 a novější: Určuje, jestli je k dispozici hlavička knihovny pro zahrnutí:

#ifdef __has_include
#  if __has_include(<filesystem>)
#    include <filesystem>
#    define have_filesystem 1
#  elif __has_include(<experimental/filesystem>)
#    include <experimental/filesystem>
#    define have_filesystem 1
#    define experimental_filesystem
#  else
#    define have_filesystem 0
#  endif
#endif

Viz také

Direktivy preprocesoru