2013-01-22 11 views
15

stavo leggendo __noop e l'esempio MSDN èPerché e quando usare __noop?

#if DEBUG 
    #define PRINT printf_s 
#else 
    #define PRINT __noop 
#endif 

int main() { 
    PRINT("\nhello\n"); 
} 

e non vedo il guadagno sopra solo avere una macro vuota:

#define PRINT 

Il codice generato è lo stesso. Qual è un esempio valido dell'uso di __noop che lo rende effettivamente utile?

+0

Immagino che ci siano situazioni in cui "nessuna affermazione" altera il funzionamento delle cose. Non sono del tutto sicuro di poterne pensare uno adesso '. –

+2

Btw, il loro esempio è un po 'dubbia in quanto risulta in un'espressione con un tipo diverso in modalità debug e release. Ma non è così rischioso come il tipo in modalità di debug, indipendentemente dagli "argomenti" su "PRINT"! I macro Variadic consentono una definizione migliore di #define PRINT (...) ((void) printf_s (__ VA_ARGS __)) 'e' #define PRINT (...) ((void) 0) ', e questo ti impedisce anche cercando di prendere un puntatore a funzione con '& PRINT'. –

risposta

15

I __noop specifica intrinseche che una funzione dovrebbe essere ignorato e la lista degli argomenti essere analizzato ma nessun codice essere generati per gli argomenti. È destinato all'uso nelle funzioni di debug globali che richiedono un numero variabile di argomenti.

Nel tuo caso l'argomento è chiaramente una libera espressione di effetti collaterali che può essere facilmente ottimizzata, quindi non importa.

Ma se l'espressione argomento ha effetti collaterali o è così complessa che il compilatore non può dimostrare che termina normalmente e non ha effetti collaterali, utilizzare __noop impedisce la valutazione potenzialmente costosa di tale espressione.

Il secondo vantaggio è che si comporta come una chiamata di funzione con un numero variabile di argomenti sintatticamente. Quindi sostituirlo con una chiamata di funzione non influisce sull'analisi del programma. Con alcune altre sostituzioni (come la stringa vuota), questo potrebbe essere un problema in alcune situazioni.

+0

Sì, penso che sia così. :) –

12
#define PRINT 
extern int some_complicated_calculation(); 
PRINT("%d\n", some_complicated_calculation()); 

chiamerebbe la funzione anche se non si desidera il risultato.

Utilizzando __noop, la funzione non verrà chiamata.

Si potrebbe (assumendo che il compilatore supporti macro variadic) definire PRINT per ignorare gli argomenti; ma in seguito non verranno analizzati e potrebbero non essere più validi se si modifica il codice che li circonda senza compilare la variante che definisce PRINT per fare qualcosa. Utilizzando __noop, gli argomenti vengono ancora analizzati, quindi è più probabile che rimangano validi.

Problemi correlati