#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.
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__
.