Sdílet prostřednictvím


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

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

Gramatika

podmíněný :
if-part elif-partsopt else-partopt-line

if-part :
If-line text

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

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

elif-line :
#elif výraz konstanty

else-part :
else-line text

else-line :
#else

endif-line :
#endif

Poznámky

Každá direktiva #if ve zdrojovém souboru musí odpovídat koncové direktivě #endif. Mezi direktivy #if a #endif se může objevit libovolný počet direktiv #elif, ale je povolena maximálně jedna direktiva #else. #else směrnice, 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á #else, #elif nebo direktiva #endif patří k nejbližší předchozí direktivě #if.

Všechny direktivy podmíněné kompilace, například #if a #ifdef, musí odpovídat závěru #endif direktivě 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 include, musí splňovat stejné podmínky: Na konci souboru include nesmí existovat žádné direktivy podmíněné kompilace.

Nahrazení makra se provádí v rámci řá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, preprocesor provede tyto direktivy. Kompilují se pouze textové bloky vybrané preprocesorem.

Preprocesor vybere jednu textovou položku vyhodnocením konstantního výrazu za každým #if nebo direktivou #elif, dokud nenajde skutečný (nenulový) konstantní výraz. Vybere veškerý text (včetně jiných direktiv preprocesoru začínajících #) až do přidružených #elif, #else nebo #endif.

Pokud jsou všechny výskyty konstantního výrazu false nebo pokud se nezobrazí žádné direktivy #elif, preprocesor vybere blok textu za klauzulí #else. Pokud neexistuje žádná klauzule #else a všechny instance konstantního výrazu v bloku #if jsou nepravdivé, není vybraný žádný blok textu.

Výraz konstanty je celočíselná konstanta výraz s těmito další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 ani operátor přetypování typu.

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

  • Překlad představuje typ int stejně jako typ longa unsigned int stejný jako unsigned long.

  • Translator 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

Operátor preprocesoru definovaný lze použít ve speciálních konstantních výrazech, jak je znázorněno následující syntaxí:

defined( identifier )
definovaný identifikátor

Tento konstantní výraz je považován za pravdivý (nenulový), pokud je identifikátor aktuálně definován. 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 direktivě #elif, ale nikde jinde.

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

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

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

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 je true. V opačném případě se příkazy po #else zpracovávají.

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

#elif DLEVEL > 5
display(debugptr);

je zkompilován a STACK není definován.

Běžným použitím podmíněné kompilace je zabránit více zahrnutí stejného souboru hlaviček. V jazyce C++, kde jsou třídy často definovány v souborech hlaviček, lze konstrukty podobné této použít k zabránění 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, je konstanta EXAMPLE_H definována tak, aby označí příklad. H jako již zpracováno.

__has_include

Visual Studio 2017 verze 15.3 a novější: Určuje, jestli je hlavička knihovny k dispozici 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