2010-09-28 20 views
6

Ho la seguente macro:C preprocessore con if

#define IF_TRACE_ENABLED(level) if (IsTraceEnabled(level)) 

Il codice utente deve cercare seguente:

IF_TRACE_ENABLED(LEVEL1) 
{ 
    ... some very smart code 
} 

L'enfasi sulla parentesi graffe - Voglio evitare che "se" da macro per "mangiare" altro codice:

if (...) 
    IF_TRACE_ENABLED(LEVEL1) 
     printf(....); 
else 
    bla bla bla 

In questo esempio IF_TRACE_ENABLED "mangia" blocco else.

C'è modo di far rispettare il codice utente non compilato senza freni ricci o ce ne sono altri per definire la macro per raggiungere la sicurezza?

+2

Non riesco a vedere che cosa ti dà questa macro oltre la semplice istruzione. – JeremyP

+2

Dimentica questo esempio. Potresti avere una condizione complicata in quel 'se' che non vuoi ripetere ogni volta. –

+0

@JeremyP: non c'è molta utilità nell'avere una macro per questo semplice esempio, ma come indica Nathan è possibile che ci possa essere più complessità nella macro di debug e/o che ci siano diverse varianti della macro basate sulla configurazione di build (per esempio, una versione di versione che valuta sempre 'false' in modo che le stringhe di traccia vengano eliminate dall'eseguibile). –

risposta

11

Questo non costringe l'utente della macro da utilizzare parentesi, ma impedisce una clausola else venga inavvertitamente mangiato:

#define IF_TRACE_ENABLED(level) if (!IsTraceEnabled(level)) {} else 

A lato nota: parentesi intorno printf() nel secondo esempio di la domanda non avrebbe risolto il problema: il else associato allo bla bla bla sarebbe comunque associato all'istruzione if nella macro.

+1

Provando e non riuscendo a trovare un modo in cui questo potrebbe ritorcersi contro. +1 –

+0

Dove viene passato il contenuto del blocco "if"? – dimba

+1

nel blocco else; bella risposta! –

0

Questo dovrebbe funzionare, ma si dovrà passare il contenuto del blocco if come argomento per la macro così:

#define IF_TRACE_ENABLED(level,content) { if (IsTraceEnabled(level)) {content} } 
+0

Non è necessario printf (...). Potrebbe trattarsi di qualsiasi codice che dovrebbe essere valutato solo quando la condizione macro è vera. – dimba

+0

È necessario aggiungere un blocco attorno al contenuto. –

+0

@Ronny - questo è ciò che voglio far rispettare all'utente, quindi se dimentica di farlo, la compilazione fallirà – dimba

2

si potrebbe provare questo:

#define IF_TRACE_ENABLED(level) do { if(IsTraceEnabled(level)) { 
#define END_TRACE_ENABLED } } while(0); 

I non pensare che ci sia un modo per "applicare" una buona sintassi solo dalla linea di apertura della macro. Dovrai usarne due.

EDIT

ho aggiunto un paio di parentesi graffe all'interno della macro di evitare ogni ambiguità.

In risposta al commento, questa macro è destinato a essere utilizzato in questo modo:

IF_TRACE_ENABLED(LEVEL1) 
    printf("Trace\n"); 
END_TRACE_ENABLED 

Non come una dichiarazione. Per la cronaca, penso che questo sia un abuso del preprocessore e nessuno dovrebbe farlo affatto. Cosa c'è di sbagliato con la sola scrittura, tra parentesi con #ifdef DEBUG se necessario.

+0

L'unica cosa che non mi piace nella soluzione è il rientro del blocco tra stat e stop macro - il tuo editor non lo farà rientrare. – dimba

+1

non è possibile usare semplicemente le parentesi, senza fare & while? –

+0

@ptmato: c'è qualcosa in quello che dice @crypto. do/while è usato per far sì che la macro assomigli alla normale funzione, da ciò che è forzato a usare ";" alla fine. Così ";" alla fine della macro è ridondante. In qualsiasi modo non ";" dal momento che la macro non assomiglia a una funzione chiama – dimba