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.