Confronto macro if-direttiva


25

Perché è #ifsoddisfatta la condizione nel seguente codice:

#include <iostream>
#define VALUE foo    

int main() {    
#if VALUE == bar
    std::cout << "WORKS!" << std::endl;
#endif // VALUE
}

Risposte:


26

La pagina su cppreference.com afferma:

Dopo tutta l'espansione e la valutazione delle macro di espressioni definite e __has_include (dal C ++ 17), qualsiasi identificatore che non è un letterale booleano viene sostituito con il numero 0 (questo include identificatori che sono parole chiave lessicali, ma non token alternativi come e ).

Quindi entrambi fooe barvengono sostituiti con 0.


Che dire di C ++ 98, C ++ 03, C ++ 11 e C ++ 14?
— Kelalaka,

1
@kelalaka È tutto uguale. È così da quando C89.
— SS Anne,

1
@kelalaka Il termine "since C ++ 17" si riferisce solo alla parte "e __has_include". Prima di C ++ 17 era lo stesso, solo con quella parte omessa.
— BessieTheCow,

15

In una #ifdichiarazione, qualsiasi identificatore che rimane dopo la sostituzione della macro (ad eccezione ditrue e false) viene sostituito con la costante 0. Quindi la tua direttiva diventa

#if 0 == 0

che è vero.


Per chiarire, '#define VALUE foo' definisce il simbolo 'VALUE' per risolvere allo stesso valore del simbolo 'foo', ma il simbolo 'foo' non ha significato, quindi verrà interpretato come 0.
— ManicDee

14

Questo perché fooné a nessuno dei due barè stata data alcuna definizione o valore, quindi sono uguali (ovvero sostituiti con un valore "0"). I compilatori daranno avvertimenti a riguardo.

Il MSVC compilatore (Visual Studio 2019) fornisce quanto segue:

avviso C4668: 'pippo' non è definito come una macro del preprocessore, sostituendo con '0' per '# if / # elif'
avviso C4668: 'bar' non è definito come una macro del preprocessore, sostituendo con '0' per '#if / # elif'

Quindi VALUEviene dato il valore '0' (predefinito per foo) ebar ha anche '0', quindi VALUE == barrestituisce "VERO".

Allo stesso modo, clang-clfornisce quanto segue:

avvertimento: 'pippo' non è definito, restituisce 0 [-Wundef]
avvertimento: 'barra' non è definito, restituisce 0 [-Wundef]


L'avvertenza è obbligatoria o è una caratteristica dei compilatori?
— Kelalaka,

1
@kelalaka Per quanto ne so, nessun "avvertimento" del compilatore è obbligatorio! Anche con i compilatori MSVCe clang-cl, questo avviso può essere disabilitato (in modo specifico o impostando un "livello" di avviso appropriato).
— Adrian Mole il

0

Per realizzare ciò che cerchi, prova questo:

#include <iostream>
#define DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

In questo caso è possibile disattivare le istruzioni di debug modificando "define" in "undef".

#include <iostream>
#undef DEBUG  

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

Potresti scoprire che il tuo compilatore ti consente di definire DEBUG al di fuori del codice stesso, a quel punto puoi ridurre il codice

#include <iostream>

int main() {    
#ifdef DEBUG
    std::cout << "WORKS!" << std::endl;
#endif
}

E quindi invoca il compilatore con un'opzione come -DDEBUG = 0

Guarda il capitolo sulla programmazione difensiva in Steve McConnell, "Codice completo".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.