Come per molte domande, la risposta a questa domanda è dipende . Invece di dire che è meglio ho piuttosto fornito esempi e obiettivi in cui uno è migliore dell'altro.
Sia il preprocessore che la costante hanno i propri luoghi di utilizzo appropriato.
In caso di pre-processore, il codice viene rimosso prima del tempo di compilazione. Quindi, è più adatto per le situazioni in cui è previsto che il codice non sia compilato . Questo può influenzare la struttura del modulo, le dipendenze e può consentire di selezionare i migliori segmenti di codice per gli aspetti delle prestazioni. Nei seguenti casi, è necessario dividere il codice solo con il preprocessore.
-
Codice multipiattaforma:
Ad esempio, quando il codice è compilato su piattaforme diverse, quando il codice ha dipendenza da specifici numeri di versione del sistema operativo (o anche dalla versione del compilatore - sebbene questo sia molto raro). Ad esempio, quando si hanno a che fare con le controparti di codice big-endien little-endien, devono essere separati dai preprocessori piuttosto che dalle costanti. Oppure se stai compilando il codice per Windows e Linux e alcune chiamate di sistema sono molto diverse.
-
Patch sperimentali:
Un altro caso in cui questo è giustificato è un codice sperimentale che è rischioso o alcuni moduli principali che devono essere omessi che avranno un collegamento significativo o una differenza di prestazioni. Il motivo per cui si vorrebbe disabilitare il codice tramite il preprocessore piuttosto che nascondersi sotto if () è perché potremmo non essere sicuri dei bug introdotti da questo specifico set di modifiche e stanno funzionando in base sperimentale. Se fallisce, non dobbiamo fare altro che disabilitare quel codice in produzione che riscrivere. A volte è ideale utilizzare #if 0
per commentare l'intero codice.
-
Affrontare le dipendenze:
Un altro motivo per cui si potrebbe voler generare Ad esempio, se non si desidera supportare le immagini JPEG, è possibile evitare di compilare quel modulo / stub e alla fine la libreria non collegherà (staticamente o dinamicamente) a quel modulo. A volte i pacchetti eseguono ./configure
per identificare la disponibilità di tale dipendenza e se le librerie non sono presenti, (o l'utente non vuole abilitare) tale funzionalità è disabilitata automaticamente senza collegamento con quella libreria. Qui è sempre utile se queste direttive sono generate automaticamente.
-
su licenza:
Un esempio molto interessante della direttiva del preprocessore è ffmpeg . Ha codec che possono potenzialmente violare i brevetti con il suo uso. Se scarichi il codice sorgente e compili per l'installazione, ti chiede se vuoi o tieni da parte tali cose.
Mantenere i codici nascosti in alcune condizioni se può ancora portarti in tribunale!
-
Codice copia-incolla:
A.k.a macro. Questo non è un consiglio per l'uso di macro - solo che le macro hanno un modo molto più efficace per applicare l'equivalente di copy-past . Ma usalo con molta cura; e usalo se sai cosa stai facendo. Le costanti, naturalmente, non possono farlo. Ma si può usare anche inline
se questo è facile da fare.
Quindi quando usi le costanti?
Quasi ovunque.
-
Flusso di codice più aggiornato:
In generale, quando si usano le costanti, è quasi indistinguibile dalle variabili regolari e, quindi, è un codice più leggibile. Se scrivi una routine che è di 75 linee - hai 3 o 4 righe dopo ogni 10 righe con #ifdef è MOLTO incapace di leggere . Probabilmente ha una costante primaria governata da #ifdef e la usa in un flusso naturale ogni dove.
-
Codice ben indentato:
Tutta la direttiva per il preprocessore, non funziona mai bene con altrimenti codice ben indentato . Anche se il tuo compilatore consente il rientro di #def, il preprocessore Pre-ANSI C non ha consentito lo spazio tra l'inizio di una riga e il carattere "#"; il "#" iniziale doveva essere sempre inserito nella prima colonna.
-
Configurazione:
Un altro motivo per cui costanti / o variabili hanno senso è che possono facilmente evolvere dall'essere o collegati a globali o in futuro possono essere estesi per essere derivati dai file di configurazione.
Un'ultima cosa:
Mai USARE direttive preprocessore #ifdef
a #endif
attraversando lo scope o { ... }
. vale a dire inizio di #ifdef
o fine di #endif
su lati diversi di { ... }
. Questo è estremamente cattivo; può essere fonte di confusione, può essere talvolta pericoloso.
Questo ovviamente non è un elenco esaustivo, ma mostra una netta differenza, in cui il metodo è più adatto. Non si tratta in realtà di che è meglio , è sempre più di quale è più naturale da utilizzare in un dato contesto.