Cosa fa esattamente un blocco #if 0… #endif?


124

In C / C ++

Cosa succede al codice inserito tra un blocco #if 0/ #endif?

#if 0

//Code goes here

#endif

Il codice viene semplicemente saltato e quindi non viene eseguito?


17
Questa è una tecnica utilizzata per commentare grandi quantità di codice o per consentire il test dell'inclusione di blocchi di codice. Senza questa funzione, si dovrebbe anteporre a ciascuna riga //o iniziare la sezione con /*e terminare la sezione con */. Il problema con le ultime tecniche è che i commenti non si annidano, quindi lo sviluppatore deve controllare e gestire qualsiasi */tra l'inizio e la fine.
Thomas Matthews

Risposte:


141

Non solo non viene eseguito, ma non viene nemmeno compilato.

#ifè un comando del preprocessore, che viene valutato prima dell'effettiva fase di compilazione. Il codice all'interno di quel blocco non appare nel binario compilato.

Viene spesso utilizzato per rimuovere temporaneamente segmenti di codice con l'intenzione di riattivarli in seguito.


1
Questo è vero per qualsiasi tipo di commento. La differenza importante è l'annidamento.
Samy Bencherif

73

È identico a commentare il blocco, tranne con una differenza importante: l'annidamento non è un problema. Considera questo codice:

foo();
bar(x, y); /* x must not be NULL */
baz();

Se voglio commentarlo, potrei provare:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt. Errore di sintassi! Perché? Poiché i commenti di blocco non si annidano e quindi (come si può vedere dall'evidenziazione della sintassi di SO) il */dopo la parola "NULL" termina il commento, rendendo la bazchiamata non commentata e il */dopo bazun errore di sintassi. D'altro canto:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

Funziona per commentare l'intera cosa. E le #if 0s si annideranno l'una con l'altra, in questo modo:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

Anche se ovviamente questo può creare un po 'di confusione e diventare un problema di manutenzione se non commentato correttamente.


5
Nota che il codice all'interno di #if deve essere lessicalmente corretto (al contrario dei commenti) e le direttive del preprocessore sono ancora in vigore (idem).
jpalecek

@ David: non è corretto dal punto di vista lessicale, ma verrà comunque compilato. Quindi il codice non deve essere lessicalmente corretto.
Dennis Zickefoose

1
@ Dennis, ottengo foo.c:3: unterminated string or character constantda gcc, cosa stai usando?
David X

18

Commenta permanentemente quel codice in modo che il compilatore non lo compili mai.

Il programmatore può successivamente modificare #ifdef per fare in modo che il codice venga compilato nel programma, se lo desidera.

È esattamente come se il codice non esistesse.


15

Cosa fa esattamente un blocco #if 0… #endif?

Ti dice che l'autore ovviamente non ha mai sentito parlare di un sistema di controllo delle versioni. Il che, a sua volta, ti dice di scappare il più lontano possibile ...


12

Vorrei aggiungere per il #elsecaso:

#if 0
   /* Code here will NOT be complied. */
#else
   /* Code will be compiled. */
#endif


#if 1
   /* Code will be complied. */
#else
   /* Code will NOT be compiled. */
#endif

7

Quando il preprocessore vede #if controlla se il token successivo ha un valore diverso da zero. Se lo fa, mantiene il codice in giro per il compilatore. In caso contrario, si elimina quel codice in modo che il compilatore non lo veda mai.

Se qualcuno dice #if 0 sta effettivamente commentando il codice in modo che non venga mai compilato. Puoi pensare a questo come se avessero messo / * ... * / attorno ad esso. Non è proprio la stessa cosa, ma ha lo stesso effetto.

Se vuoi capire cosa è successo in dettaglio, puoi spesso guardare. Molti compilatori ti permetteranno di vedere i file dopo che il preprocessore è stato eseguito. Ad esempio, in Visual C ++ il comando switch / P eseguirà il preprocessore e inserirà i risultati in un file .i.


Non proprio. Il preprocessore analizza per riga invece che per token. Secondo la tua spiegazione non sarebbe possibile dire ad es. #if WIN32 || __CYGWIN__Ma funziona come previsto.
Ben Voigt

Stavo semplificando. Se è presente un o, controllerà se uno dei token è diverso da zero. Allo stesso modo se c'è un e controllerà se entrambi sono diversi da zero.
Steve Rowe

3

Le righe che iniziano con a #sono direttive del preprocessore . #if 0 [...] #endifi blocchi non arrivano al compilatore e non genereranno codice macchina.

Puoi dimostrare cosa succede con il preprocessore con un file sorgente ifdef.cxx:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

L'esecuzione gcc -E ifdef.cxxti mostrerà cosa viene compilato.

Puoi scegliere di utilizzare questo meccanismo per impedire che un blocco di codice venga compilato durante il ciclo di sviluppo, ma probabilmente non vorrai archiviarlo nel tuo controllo del codice sorgente poiché aggiunge semplicemente cruft al tuo codice e riduce la leggibilità. Se è un pezzo storico di codice che è stato commentato, allora dovrebbe essere rimosso: il controllo del codice sorgente contiene la cronologia, giusto?

Inoltre, la risposta potrebbe essere la stessa sia per C che per C ++ ma non esiste un linguaggio chiamato C / C ++ e non è una buona abitudine fare riferimento a tale linguaggio.


4
Cosa c'è di sbagliato nel dire C / C ++ come abbreviazione di "C o C ++"? Pensi onestamente che qualcuno sarà confuso nel pensare che esista un linguaggio chiamato "C / C ++"?
Christopher Barber

1
@ Chris: Le persone fanno costantemente domande come "Come faccio a fare X in C / C ++?" Che è una domanda senza senso; stai codificando nell'uno o nell'altro, e se non hai ancora scelto dovresti essere esplicito in questo fatto. Quindi, sì, le persone sono confuse sul fatto che esista un linguaggio chiamato "C / C ++"
Dennis Zickefoose

1
Che affermazione senza senso! Esistono migliaia di domande le cui risposte sono rilevanti sia per C che per C ++. Ricorda che questo è un sito per porre domande. Solo perché stai facendo una domanda generale non significa che non sai quale lingua stai usando. Se sospetti che sia così, come in questa domanda, come aiuta a specificare C o C ++? Pensi che sarebbe utile se ogni domanda che potrebbe essere applicata a C o C ++ venisse posta due volte?
Christopher Barber

@Christopher: Hai ragione, ci sono molte domande in cui le risposte sono altrettanto rilevanti per C, C ++ e Objective-C (questa è una di queste). Stack Overflow ha un pratico sistema di tagging per indicare a quali lingue appartiene una domanda. Come cita @Dennis, SO (e altri forum di programmazione [forum?]) Ci sono (troppe) persone confuse sulla delineazione tra C e altri linguaggi derivati ​​dal C che si riferiscono a questi linguaggi in modo intercambiabile come C / C ++ rendendolo più difficile rispondere alla domanda nella lingua appropriata.
Johnsyweb

2

Non proprio

int main(void)
{
   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;
}

Mostra "tc: 4: 19: warning: carattere di terminazione mancante" con gcc 4.2.4


2
Questo avviso viene generato dal preprocessore, non dal compilatore. Il compilatore può vedere solo: # 1 "tc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tc" int main (void) {return 0; }
Johnsyweb

0

È un modo economico per commentare, ma sospetto che possa avere un potenziale di debug. Ad esempio, supponiamo di avere una build che restituisce valori in un file. Potresti non volerlo in una versione finale, quindi puoi usare #if 0 ... #endif.

Inoltre, sospetto che un modo migliore per farlo a scopo di debug sarebbe quello di fare:

#ifdef DEBUG
// output to file
#endif

Puoi fare qualcosa del genere e potrebbe avere più senso e tutto ciò che devi fare è definire DEBUG per vedere i risultati.

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.