L'uso delle macro C / C ++ come scelta rapida per la compilazione condizionale è una buona pratica?


13

Diciamo che voglio avere diversi tipi di messaggi di output nel mio codice. Uno di questi è DEBUG, che viene stampato solo, quando il codice viene compilato in modalità Debug.

Di solito dovrei scrivere qualcosa del genere

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

che è piuttosto ingombrante e fastidioso da usare in molti luoghi.

È buona norma definire una macro per lo snippet di codice, quindi la useresti in questo modo?

MSG_DEBUG("Debug message")

O c'è un altro modo più elegante come affrontarlo senza macro? Sono interessato a possibili soluzioni sia in C che in C ++, poiché sto usando entrambe le lingue in diversi progetti.



Non è chiaro dalla domanda perché non si debba semplicemente inserire il codice condizionale in una funzione e chiamarlo. C'è qualche altro vincolo che lo impedirebbe?
Alex,

@gnat La domanda che hai menzionato è così ampia, che la maggior parte delle persone non la collegherebbe a questo argomento, specialmente quando cercherebbe questa domanda specifica su Internet.
Eenoku,

3
La tua domanda è taggata con c e c ++ , tuttavia, sono linguaggi piuttosto diversi. Puoi chiarire di chi stai parlando? Il tuo esempio andrebbe perfettamente bene in C, ma potrebbe essere meglio implementato con un constexpr ifin C ++, per esempio.
Jörg W Mittag,

1
A parte questo, la diagnostica dovrebbe andare a STDERR. Inoltre, perché non farlo dipendere da NDEBUGcome assert()fa invece? Quindi potresti definirlo come #define DEBUG_MSG(MSG) assert(std::cerr << MSG), che verifica anche lo stato del flusso.
Deduplicatore,

Risposte:


19

Certo, se stai bene usando le macro in primo luogo, allora definirne uno parametrizzato piuttosto che continuare a ripetere lo stesso codice condizionale è sicuramente preferibile da qualsiasi misura di buona codifica.

Dovresti usare le macro? Dal mio punto di vista dovresti, dato che è accettata la pratica in C, e qualsiasi soluzione senza macro richiederebbe almeno qualcosa da eseguire anche al di fuori della modalità di debug. Il programmatore C tipico sceglierà una macro leggermente brutta in qualsiasi momento di runtime non necessario.


13

C'è un elemento di preferenza personale qui, ma in C ++ preferisco farlo nel file di intestazione:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

In modo che la funzione sia integrata nelle build di rilascio, ma sia una funzione corretta nella build di debug in modo da poter avere il controllo del tipo corretto, messaggi di errore sensibili, ecc. E la possibilità di aggiungere ulteriori funzionalità (registrazione forse?) In seguito.

Ovviamente, è anche necessario racchiudere .cppin un #ifdef _DEBUGblocco la corrispondente definizione della funzione nel file .


Ma l'overhead della chiamata è ancora presente qui, non è vero?
Eenoku,

7
Se il compilatore genererà il codice per chiamare una funzione vuota nota in una build di rilascio, la prima e più grande cosa che devi fare per migliorare l'efficienza è ottenere un compilatore molto migliore. Questa è un'ottimizzazione davvero banale.
David Thornley,

@Eenoku No, come dice David, verrà rimosso da qualsiasi compilatore che dovresti usare.
Jack Aidley,

3
C'è una differenza fondamentale qui: la macro (a seconda di come è scritta) non valuterà le sue espressioni di argomento, mentre la funzione lo farebbe sempre. Inoltre, è un comportamento indefinito passare argomenti non banali alle funzioni varargs (e di solito innesca avvisi del compilatore).
Sebastian Redl,


2

Sicuramente, assicurati di non calpestare le linee guida sul codice fornite dal tuo team. Assicurarsi che nessun altro codice nel sistema tenti di raggiungere la stessa funzionalità tramite una condizione if generale.

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.