2012-09-15 10 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__)) 

Dies ist die Definition für diese 2 Makros; später im Code LOGI und LOGW werden auf diese Weise verwendenEin #define in C mit drei Punkten

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

und auf diese Weise

LOGW("Unable to eglMakeCurrent"); 

Da ich versuche, komplexe Makros und #define im Allgemeinen zu vermeiden, kann ich nicht bekommen, was dieses Makro tatsächlich Mittel . Was ist die Rolle für die 3-Punkte-Notation hier? Was ändert sich #define später im Code?

Offensichtlich weiß ich, dass die 3 Punkte verwendet werden, um eine unbegrenzte Anzahl von Argumenten anzugeben, aber ich weiß nicht, wie ich diese Situation lesen soll.

+4

Es heißt ein variadic Makro. http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html – chris

+0

@chris also ist es eine Möglichkeit zu versuchen, weniger wortreich zu sein und die Argumente in einer bestimmten Weise neu zu ordnen? – Ken

+0

Hmm, ich hätte '## __ VA_ARGS__' verwendet, aber ich denke, es ist in Ordnung, solange du ein Argument geben musst. – nneonneo

Antwort

14

Der C99-Standard eingeführt variadic Makros, d. H. Funktionsähnliche Makros, die eine variable Anzahl von Argumenten annehmen können.

Zitiert die latest draft der C-Standard, Abschnitt 6.10.3:

Wenn der Identifikator-Liste in der Makrodefinition nicht mit einem Auslassungs enden, die Anzahl der Argumente (einschließlich der Argumente bestehend (keine Vorverarbeitungstoken) in einem Aufruf eines funktionsähnlichen Makros entspricht der Anzahl der Parameter in der Definition des Makros . Andernfalls müssen mehr Argumente im Aufruf vorhanden sein, als Parameter in der Makrodefinition vorhanden sind (mit Ausnahme der ...). Es soll a) ein Vorverarbeitungstoken existieren, das den Aufruf beendet.

Die Kennung __VA_ARGS__ nur in der Ersatz-Liste der eine funktionsähnliche Makro auftreten, die die Ellipsen-Notation in den Parametern verwendet.

...

Wenn es eine ... in der Identifikator-Liste in der Makrodefinition ist, dann werden die nachlauf Argumente, einschließlich etwaiger Trenn Komma Vorverarbeiten Tokens, werden zusammengeführt eine einzige zu bilden Artikel: Variable Argumente. Die Anzahl der so kombinierten Argumente ist so, dass die Anzahl der Argumente nach der Zusammenlegung um eins mehr ist als die Anzahl der Parameter in der Makrodefinition (mit Ausnahme der ...).

Und im nächsten Abschnitt:

Eine Kennung __VA_ARGS__, die behandelt werden soll in der Ersatzliste tritt , als ob es ein Parameter war, und die variablen Argumente sind die Vorverarbeitung Token bilden verwendet ersetze es.

So können Sie LOGI oder LOGW mit so vielen Argumente aufrufen, wie Sie wollen, und sie werden alle in der in der Definition durch den Verweis auf __VA_ARGS__ angegebenen Ort erweitert werden.

+0

Übrigens, ist '## __ VA_ARGS__' (normalerweise verwendet, um den Fall von Nullargumenten zu behandeln, die einem variadischen Makro zur Verfügung gestellt werden), die vom Standard erlaubt sind? Ist es überhaupt notwendig? – nneonneo

+0

Die Schreibweise '## __ VA_ARGS__' ist eine GCC-Erweiterung. –

+0

Ja, es ist eine Erweiterung und kann durch andere Techniken ersetzt werden, die die Anzahl der Argumente zählen, die das Makro empfängt. –