2010-01-18 10 views

risposta

0

Questo è a volte utile in un dominio molto chiuso per la definizione delle fasi di processo in modo più leggibile:

void myfunc() { 
    DO_STEP_ONE; 
    THEN_ANOTHER_STEP; 
    KEEP_GOING; 
    LAST_STEP; 
} 

Ma di solito fa solo codice più difficile da leggere e capire.

A meno che non valga la pena che i lettori del tuo codice conoscano il significato di quei # define, ed è una specie di scorciatoia, stai semplicemente facendo in modo che le persone guardino in due punti per capire una linea di codice (top di file e in funzione) piuttosto che uno.

Uso molto raramente questo tipo di approccio.

+0

utilizzando macro per questo non è più leggibile rispetto all'utilizzo di funzioni con lo stesso nome – user463035818

0

che dipenderà la lingua, compilatore, ecc, ecc, ecc ...

Tuttavia, non c'è niente di sbagliato con esso, una volta come il nome implica tali direttive si verifica in precedenza il processo di compilazione.

Il pre-processore di rimuovere tutti i riferimenti costanti per il suo valore reale, tutte le pseudo-funzione con il codice appropriato, e così via ...

0

Tutti i problemi in informatica può essere risolto da un altro livello di indirezione

Questo è uno di questi livelli indirezione in più :-)

dire che ad un certo punto che la funzione ha bisogno di un altro argomento o non avete bisogno per chiamarlo a tutti, è possibile modificare il #define una volta invece di modificare tutti i punti in cui viene chiamata la funzione.

Utile per lo sviluppo, ma pericoloso per mantenere il codice di produzione ... Avrei eseguito il preprocessore per sostituire quella regola una volta che ho un codice maturo e so che non avrò bisogno di cambiarlo.

+0

Che dire di avere troppi livelli di riferimento indiretto? ;) – daotoad

5

Un lato negativo? Di solito una definizione di macro non finisce nella tabella dei simboli dell'eseguibile. Un po 'più difficile eseguire il debug.

5

Il problema è che gli argomenti sono ri = valutate ogni volta che vengono utilizzati:

#define MIN(A,B) ((A) < (B))?(A):(B); 

noti che devo avvolgere tutti gli argomenti in '(' ')' per assicurarsi che l'espressione restituisce corectly . Ma cosa succede se lo facciamo?

int s = MIN(++current,Max); 

Coding questo mi aspetterei corrente da incrementato una volta prima che la funzione viene chiamata.Ma perché è una macro che viene incrementato una volta nel test e una seconda volta se è ancora più piccolo di Max

+0

Sebbene questo sia effettivamente uno svantaggio delle macro, 'gcc' fornisce * estensioni specifiche del compilatore * per risolvere il problema:' #define MIN (a, b) ({typeof (a) _a = (a); typeof (b) _b = (b); _a <_b? _a: _b;}) '. – kennytm

+0

@Kenny: la tua Macro Foo è migliore della mia. Ho provato e funziona. Anche se non sembrava, non pensavo che un'affermazione (Block) potesse funzionare come un valore. –

+0

@Kenny: Sfortunatamente, nemmeno l'estensione di gcc funzionerebbe se "MIN" venisse chiamato su variabili che erano inopportunamente chiamate '_a' e' _b'. – jamesdlin

2

Ci sono diversi problemi si può pensare di:

  • Nella macro C++ non ha namespace e ambito di classe, quindi è lo stesso ovunque. Un esempio di ciò sono gli sfortunati min e max che definiscono da qualche parte in windows.h. Se stai programmando per windows e includi windows.h e vuoi scrivere std :: numeric_limits :: max() allora max sarà sostituito da un codice ... Questo lascia codice non compilabile dopo l'esecuzione del preprocessore. (Ok, ci sono modi per disattivare i macro min/max in windows.h, ma è ancora un progetto scadente!)
  • La macro non può essere debellata correttamente. Il debugger si fermerà sulla linea la macro non è usata nel codice all'interno della macro ...
  • Possibile rivalutazione dei parametri macro (si potrebbe evitare questo avendo un blocco con variabili locali all'interno della macro ma questo farebbe il debug ancora peggio!)
0

Perché dovresti cercare degli svantaggi nell'utilizzo di un codice specifico per il preprocessore? L'utilizzo di macro del preprocessore per scopi diversi dalla compilazione condizionale (incluse le protezioni incluse) dovrebbe essere automaticamente considerato negativo. La domanda corretta da porsi è se ci sono vantaggi per un uso particolare.

Le macro di preprocessore non rispettano l'ambito o l'utilizzo in alcun modo. Possono rovinare il codice perfettamente buono in modi inaspettati e difficili da trovare. Evitali sempre a meno che tu non abbia una buona ragione per usarne uno.

1

Beh, se si deve fare che (e ci sono alcune occasioni in cui si potrebbe), allora si dovrebbe almeno definire la macro come "funzione-like" in tal modo: Codice

#define SOME_FUNCTION() someFunction(defaultArgument) 

altrimenti si sarebbe scrivere che sembrava un incarico da una costante quando in realtà era una chiamata di funzione; vale a dire;

x = SOME_FUNCTION ; // hidden function call 

ma con una macro "Funzione-like" si sarebbe obbligato a scrivere:

x = SOME_FUNCTION() ; // shorthand function-call with default argument 

che corrisponde meglio la sintassi pre-processore con la sintassi del linguaggio.

Generalmente si evitano le macro di funzione, ma alcune sono più insidiose di altre, questo non è assolutamente il caso peggiore. Tuttavia, si potrebbe facilmente scrivere un wrapper di funzione in C, o in C++ usare un argomento predefinito, e nella maggior parte dei casi sarebbe preferibile.

0

Lo svantaggio è che si nasconde il codice. Il lato positivo è che si nasconde il codice.

Il lato negativo di solito supera il lato positivo.

Di solito questo particolare approccio è praticamente inutile e meno che la chiamata sembra più

someModule-> someStorage-> functionList [storage.getFunctionName] .pointer-> SomeFunction (... altrettanto oscura argomento ...);

non ha senso farlo. Se solo l'argomento è una chiamata oscura, abbrevia l'argomento. Se è solo la funzione, abbrevia la sola funzione.Se entrambi, si potrebbe essere meglio con

SOME_FUNCTION(SOME_ARGUMENT); 

Se la funzione non viene mai chiamato con qualsiasi altra cosa, si potrebbe prendere in considerazione la rimozione dalla lista di argomenti e di ottenere all'interno del corpo della funzione. E se la coppia si ripete molto spesso, in piccole variazioni, potresti prendere in considerazione le funzioni del wrapper.

Dopo aver fatto diversi bug nel codice di una macro, imparerai che è difficile eseguirne il debug e non li userai in modo frivolo.

Problemi correlati