2012-09-15 20 views
9
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__)) 
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__)) 

Questa è la definizione per questi 2 macro; più avanti nel codice LOGI e LOGW vengono usati in questo modoA #define in C con tre punti

LOGI("accelerometer: x=%f y=%f z=%f", 
           event.acceleration.x, event.acceleration.y, 
           event.acceleration.z); 

e in questo modo

LOGW("Unable to eglMakeCurrent"); 

Dato che cerco di evitare macro complesse e #define in generale, non posso ottenere ciò che questo significa in realtà macro . Qual è il ruolo della notazione a 3 punti qui? Cosa cambia in seguito questo #define nel codice?

Ovviamente so che i 3 punti sono usati per indicare una quantità indefinita di argomenti, ma non so come leggere questa situazione.

+4

Si chiama macro variadica. http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html – chris

+0

@chris quindi è un modo per cercare di essere meno prolisso e riorganizzare gli argomenti in un certo modo? – Ken

+0

Hmm, avrei usato '## __ VA_ARGS__', ma suppongo che sia OK finchè devi dare un argomento. – nneonneo

risposta

14

Lo standard C99 ha introdotto macro variadic, ad esempio macro funzionali che possono assumere un numero variabile di argomenti.

Citando il latest draft dello standard C, sezione 6.10.3:

Se l'identificatore-elenco nella definizione macro non termina con un ellissi, il numero di argomenti (comprese quelle argomenti consistente di nessun token di preelaborazione) in un'invocazione di una macro simile alla funzione deve corrispondere al numero di parametri nella definizione della macro . In caso contrario, vi saranno più argomenti nell'invocazione rispetto a quelli nella definizione macro (escluso lo ...). Ci deve essere un token di preelaborazione che termina la chiamata .

L'identificatore __VA_ARGS__ deve avvenire solo nella sostituzione-list di una funzione macro-like che utilizza la notazione puntini di sospensione nei parametri .

...

Se c'è un ... nell'identificatore-list nella definizione della macro, poi gli argomenti di uscita, comprese eventuali che separano i token virgola pre-elaborazione, vengono uniti a formare un unico articolo: variabile argomenti. Il numero di argomenti così combinati è tale che, dopo la fusione, , il numero di argomenti è uno in più del numero di parametri nella definizione macro (escluso lo ...).

E nella prossima sottosezione:

Un identificatore __VA_ARGS__ che si verifica nella lista di sostituzione devono essere trattata come se fosse un parametro, e gli argomenti variabile formare i gettoni di pre-elaborazione utilizzati per sostituiscilo.

Quindi è possibile richiamare LOGI o LOGW con il maggior numero di argomenti che ti piace, e saranno tutti ampliato nel luogo indicato nella definizione dal riferimento alla __VA_ARGS__.

+0

A proposito, è '## __ VA_ARGS__' (comunemente usato per gestire il caso di argomenti zero forniti a una macro variadica) consentito dallo standard? È addirittura necessario? – nneonneo

+0

La notazione '## __ VA_ARGS__' è un'estensione GCC. –

+0

Sì, è un'estensione e può essere sostituita da altre tecniche che contano il numero di argomenti ricevuti dalla macro. –