2012-09-28 22 views
29

Vorrei stampare un valore di macro (espandere la macro) nella direttiva #WARNING.C preprocessore: espandere la macro in un #WARNING

Ad esempio, per il codice:

#define AAA 17 
#warning AAA = ??? 

L'uscita in fase di compilazione desiderato sarebbe

warning: AAA = 17 

Cosa posso usare per ???, o, come faccio a aumentare il codice di ?

+1

Secondo lo standard C a partire dal 1999, si hanno solo '# error' per qualcosa di simile e non espande nessuna macro, stampa semplicemente il testo letteralmente e causa la chiusura della compilazione. Cosa stai cercando di ottenere con questo comunque? –

+0

Ho una gerarchia di molti makefile che definiscono AAA in vari modi, a seconda dei parametri del make target. Vorrei verificare che la definizione sia corretta per il target. E non vorrei creare un elenco di #if AAA = 1 ... #warning "è 1" ... – elomage

+0

Inoltre, questo è per il mondo embedded senza display, quindi non posso facilmente testare il valore della macro di aggiungendo qualcosa come printf (#AAA); e controllarlo in fase di esecuzione. – elomage

risposta

37

È possibile utilizzare la direttiva preprocessore #pragma message.

Esempio:

#define STR_HELPER(x) #x 
#define STR(x) STR_HELPER(x) 

#define AAA 123 
#pragma message "content of AAA: " STR(AAA) 

int main() { return 0; } 

L'output è simile al seguente:

$ gcc test.c 
test.c:5:9: note: #pragma message: content of AAA: 123 
#pragma message("content of AAA: " STR(AAA)) 
     ^

Per riferimento:

+0

Dovresti menzionare il/i compilatore/i con cui funziona. '# pragma's' sono specifici dell'implementazione. –

+0

Funziona con gcc versione 4.5.3 (GNU GCC con patch mspgcc-20110716), grazie. – elomage

+2

assicurati di usare '#pragma message' invece di' # message' o '# warning' – fantastory

2

Molte volte ho la mia Makefile generare un file generated.h locale che contiene le definizioni desiderati.

 
generated.h: Makefile 
     echo >generated.h "// WARNING: generated file. Change Makefile instead" 
     date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S' 
     echo >>generated.h "#if AAA == AAA_bad" 
     echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" 
     echo >>generated.h "#endif"

La necessità di #include "generated.h" è evidente.

Naturalmente si può girare qualsiasi complessità qui, ma se diventa più di poche righe si può voler mettere la complessità in uno script separato come Makefiles ingombra può essere un problema di manutenzione orribile. Con un po 'di immaginazione si possono avere cicli che generano un gran numero di test da un piccolo input.

Avere il target generato.h dipende da Makefile è fondamentale per assicurare che il generato.h venga rifatto se le istruzioni nel target cambiano. Se si dispone di uno script generato.sh separato anch'esso presente nell'elenco delle dipendenze.

Esonero di responsabilità: non hanno testato per davvero.

7

non mi consiglia di utilizzare #WARNING, dal momento che non è standard C. Inoltre, ciò che è lì che si desidera mettere in guardia contro, ma non genera un errore contro? Gli avvertimenti sono in genere qualcosa che il compilatore utilizza quando stai facendo qualcosa di sospetto che è assolutamente pericoloso, ma consentito dallo standard C. Non hai questo caso nella normale applicazione, lo vuoi compilare in modo impeccabile o non farlo affatto. Quindi userò #error standard e non #warning non standard.

Non è possibile digitare il contenuto effettivo della definizione pre-processore. Qualcosa di simile potrebbe essere sufficiente:

#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE) 
    #error AAA is bad. 
#endif 

Penso che questo sia abbastanza dettagliato per il programmatore. Tuttavia, se si davvero vuole maggiori dettagli e si dispone di un moderno compilatore C, è possibile utilizzare static_assert.Poi si può ottenere qualcosa di simile a ciò che si vuole:

#include <assert.h> 

#define xstr(s) str(s) 
#define str(s) #s 
#define err_msg(x) #x " is " xstr(x) 

#define AAA 17 

static_assert(AAA != 17, err_msg(AAA)); 

questa macro pasticcio dovrebbe stampare AAA è 17. Una spiegazione su come queste macro lavoro può essere trovato here.

Non sono sicuro se static_assert fosse incluso in C99 o C11, è sicuramente in C11. Potrebbe essere necessario utilizzare qualche estensione GCC per abilitarlo.

+0

vedi anche [questa domanda] (http://stackoverflow.com/q/3385515/1025391) per asserzioni statiche in C – moooeeeep

+0

Ho solo bisogno di un messaggio informativo con il valore per confermare il mio sospetto che un parametro interno globale non fosse corretto per un caso particolare. Nessun valore "cattivo" qui. Si è scoperto che non era corretto. Ma grazie per static_assert, funziona dalla versione 4.3 di g ++ con l'opzione -std = C++ 0x, e gcc versione 4.6 ha static_assert con alias su _Static_assert senza l'opzione. – elomage

+0

@elomage _Static_assert è in realtà una parola chiave in C ora, dal C11. contiene una macro static_assert, che si espande in _Static_assert. Entrambe le forme dovrebbero essere belle da usare poiché sono entrambe standard. – Lundin

7

Se si desidera emettere un avviso, anche il seguente funzionerà. Tuttavia, dipende da C99 viene abilitato (funziona con gcc 4.8.2 o versioni successive, non testato su versioni precedenti):

#define N 77 

#define __STRINGIFY(TEXT) #TEXT 
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT) 
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE)) 

#if N == 77 
_Pragma (WARNING(N)) 
#endif 
Problemi correlati