13
#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__))

This is definition for these 2 macros; later in the code LOGI and LOGW are used this way

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

and this way

LOGW("Unable to eglMakeCurrent");

Since I try to avoid complex macros and #define in general, I can't get what this macro actually means. What is the role for the 3 dots notation here? What does this #define change later in the code?

Obviously I know that the 3 dots are used to indicate and indefinite amount of arguments, but I don't know how to read this situation.

a3f
  • 8,517
  • 1
  • 41
  • 46
Ken
  • 2,105
  • 3
  • 19
  • 22
  • 4
    It's called a variadic macro. http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html – chris Sep 15 '12 at 04:57
  • @chris so it's a way for trying to be less verbose and rearrange the arguments in a certain way? – Ken Sep 15 '12 at 05:03
  • Hmm, I would have used `##__VA_ARGS__`, but I guess it's OK as long as you have to give an argument. – nneonneo Sep 15 '12 at 05:04
  • 1
    @Ken: A variadic macro lets the macro take an arbitrary number of arguments (similar in spirit to the `printf` function). That way, you can give a macro a format string and arguments to the format string. It is, as you see here, most commonly used to wrap variadic functions. – nneonneo Sep 15 '12 at 05:05

1 Answers1

17

The C99 standard introduced variadic macros, i.e., function-like macros that can take a variable number of arguments.

Quoting the latest draft of the C standard, section 6.10.3:

If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments (including those arguments consisting of no preprocessing tokens) in an invocation of a function-like macro shall equal the number of parameters in the macro definition. Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...). There shall exist a ) preprocessing token that terminates the invocation.

The identifier __VA_ARGS__ shall occur only in the replacement-list of a function-like macro that uses the ellipsis notation in the parameters.

...

If there is a ... in the identifier-list in the macro definition, then the trailing arguments, including any separating comma preprocessing tokens, are merged to form a single item: the variable arguments. The number of arguments so combined is such that, following merger, the number of arguments is one more than the number of parameters in the macro definition (excluding the ...).

And in the next subsection:

An identifier __VA_ARGS__ that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it.

So you can invoke LOGI or LOGW with as many arguments as you like, and they'll all be expanded at the place specified in the definition by the reference to __VA_ARGS__.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631