A #define in C with three dots - c

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

Related

In what situations does C preprocessor ## work and not work?

It seems that sometimes concatenation with ## does work and sometimes it does not work.
It is an unreliable feature even though it is clearly vitally necessary for some uses.
Is there a clear set of rules for using ##?
An example is:
file1.h
#define concat(a,b) a##b
#define BAR bar
extern int concat(fu,BAR) ();
Here concat produces fuBAR not fubar.
An example is:
file2.h
#define BAR bar
extern int fu##BAR ();
Here ## produces an error about a stray ## in the code.
## obeys rules which are different than the rules you were expecting. That doesn't mean it "doesn't work" or "is an unreliable feature", it only means you have to use it differently than you thought.
When you write
#define concat(a,b) a##b
the C standard says that the arguments a and b are NOT macro expanded before the concatenation happens. (N1570 §6.10.3.1.) This is an intentional difference from the behavior when you don't apply ## or # to a macro argument.
You can get the behavior you wanted with double expansion:
#define concat(a,b) concat_(a,b)
#define concat_(a,b) a##b
With this definition, the arguments to concat are macro expanded before substitution into the macro body, since they are not being used as operands to ##. Then each argument becomes an argument to concat_, and isn't expanded again, but that's fine, because the expansion is done already.
And when you write
#define BAR bar
extern int fu##BAR ();
the C standard says that the ## operator is not recognized at all by the preprocessor (and therefore passes on to translation phase 7, where it is a valid token that isn't accepted by any grammar rule, and therefore causes a syntax error) because it's not part of a macro definition. (N1570 §6.10.3.3p2,3 — by implication only; it says that ## is recognized when it appears in the replacement list of a macro being expanded. This section doesn't say that it is recognized at any other time, and no other part of the standard gives ## a meaning in any other context.)
Is there a clear set of rules for using ##?
The C standard 6.10.3.1:
After the arguments for the invocation of a function-like macro have been identified,
argument substitution takes place. A parameter in the replacement list, unless preceded
by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is
replaced by the corresponding argument after all macros contained therein have been
expanded.
Basically the ## concatenation happens before token expansion, because the result of ## could result in a new preprocessor token. In case we have this:
#define concat(a,b) a##b
#define BAR bar
#define fuBAR "hello world"
Then puts(concat(fu,BAR)); will print "hello world".
In order to fix this, you need a helper macro which expands the preprocessor tokens before passing them to the macro where ## (or #) resides:
#define cc(a,b) a##b
#define concat(a,b) cc(a,b)
#define BAR bar
#define fuBAR "hello world"
#define fubar "fubar"
In this example a and b are expanded to fu and bar before cc is invoked. So now puts(concat(fu,BAR)); will print "fubar".
Here ## produces an error about a stray ## in the code.
Because you can only use # and ## inside macros, simple as that. extern int fu##BAR (); is not a macro.
It seems that sometimes concatenation with ## does work and sometimes it does not work.
That's like saying "sometimes multiplication with * does work, and sometimes it doesn't", and then presenting examples such as
int six = 5;
int product = six * 2; // results in 10 instead of 12
and
void f(int a, int b, int a * b); // rejected by the compiler
The specifications for the token-pasting operator are presented in 6.10.3.3 of the C17 language specification, and your first clue should be that this is a subsection of 6.10.3, which describes macro replacement. Not only the placement of the section but also its explicit text make it clear that token concatenation occurs (only) in the context of macro replacement:
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
(C17 6.10.3.3/3)
There are no other specifications for special treatment of ##, so that's its full scope.
Additionally,
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding
argument after all macros contained therein have been expanded.
(C17 6.10.3.1/1; emphasis added)
Thus, where function-like macro arguments are operands of a ## (or #) operator, they are not themselves macro-expanded, though the concatenated result might be expanded as a macro when the result is re-scanned.

Why does preprocessor macros ignore statements in parentheses

Following to my (duplicate) question ( and as suggested by StoryTeller)
Why do preprocessor macros ignore function names in parenthesis?
#include <stdio.h>
#include <stdlib.h>
#define abs(x) ((x))
int main(void)
{
printf("%d\n", abs(-1)); // output: -1
printf("%d\n", (abs)(-1)); // output: 1
return 0;
}
Is this defined in the standard?
The preprocessor's macro substitution is specified as follows:
6.10.3 Macro replacement / p10 - Emphasis mine:
A preprocessing directive of the form
# define identifier lparen identifier-list<opt> ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
defines a function-like macro with parameters, whose use is similar
syntactically to a function call. The parameters are specified by the
optional list of identifiers, whose scope extends from their
declaration in the identifier list until the new-line character that
terminates the #define preprocessing directive. Each subsequent
instance of the function-like macro name followed by a ( as the next
preprocessing token introduces the sequence of preprocessing tokens
that is replaced by the replacement list in the definition (an
invocation of the macro). The replaced sequence of preprocessing
tokens is terminated by the matching ) preprocessing token, skipping
intervening matched pairs of left and right parenthesis preprocessing
tokens. Within the sequence of preprocessing tokens making up an
invocation of a function-like macro, new-line is considered a normal
white-space character.
It says it right there in bold. For substitution to occur, the very next preprocessing token after the macro name must be a (. When it's a ), such as when the macro is in parentheses, no substitution can occur.
So that leaves us only with the function name in parentheses, an expression that is identical to the function's designator.
Why? Because the C preprocessor is agnostic of the C language!
The C preprocessor has been conceived as a pure text replacement tool, barely powerful enough to provide C programmers with a simple means to
define constants that are pasted literally into the program
literally paste the contents of files (i.e. headers) into the program
provide a simple means of creating simple templates of code, that are again pasted literally into the program
None of this includes any awareness of the C syntax! It's pure text manipulation.
On the contrary, you can do stuff like this
#define CLASS(name, base) typedef struct name name;\
struct name {\
base super;
#define END_CLASS };
CLASS(foo, bar)
int baz;
END_CLASS
Note how the preprocessor will generate an unmatched { token when expanding the CLASS macro, and an unmatched } token when expanding the END_CLASS macro.
Thus, the syntax for using a macro has nothing to do with the syntax for calling a function. You can call a C function in many different ways (foo(), foo (), (foo)(), (**(*foo) ) (), etc.) because the C language handles expressions of functions, and defines what happens when you place its name in parentheses (it's implicitly converted to a pointer to it), dereference it, or call it. All this does not exist in the preprocessor, so there is exactly one way to use a macro: foo() with no extra space between the name and the (.
Side note:
The C preprocessor is so agnostic of the C language, that it's not just used with C, it's also commonly used with languages like FORTRAN. (Which is a horrible fit, actually. Nevertheless, the C preprocessor is the best, commonly supported thing that can be used to make FORTRAN a bit less painful.)

what is ## in c?

I have seen this snippet:
#define kthread_create(threadfn, data, namefmt, arg...) \
kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)
what does ## stand for ?
what is the meaning of ## when it appears out of a macro ?
Contrary to the other answers, this is actually GCC extension. When pasting variable args directly in, a problem occurs if no extra args were passed. Thus, GCC makes ## when used with __VA_ARGS__ or a varargs variable (declared with argname...). To paste if it contains a value, or remove the previous comma if not.
The documentation for this extension is here:
Second, the '##' token paste operator has a special meaning when placed between a comma and a variable argument. If you write
#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__)
and the variable argument is left out when the eprintf macro is used, then the comma before the '##' will be deleted. This does not happen if you pass an empty argument, nor does it happen if the token preceding '##' is anything other than a comma.
eprintf ("success!\n")
==> fprintf(stderr, "success!\n");
The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. In this case the C99 standard is clear that the comma must remain, however the existing GCC extension used to swallow the comma. So CPP retains the comma when conforming to a specific C standard, and drops it otherwise.
This "pastes" whatever passed in arg to the macro expansion.
Example:
kthread_create(threadfn, data, namefmt, foo, bar, doo);
Expands to:
kthread_create_on_node(threadfn, data, -1, namefmt, foo, bar, doo);

What does this #define syntax mean?

I came across this one, don't understand.
#define IDEBUG(a...)
What does the "(a...)" mean?
That's a variadic macro.
Quoting verbatim from the linked page:
A macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function. Here is an example:
#define eprintf(...) fprintf (stderr, __VA_ARGS__)
This kind of macro is called variadic. When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none), including any commas, become the variable argument. This sequence of tokens replaces the identifier VA_ARGS in the macro body wherever it appears. Thus, we have this expansion:
eprintf ("%s:%d: ", input_file, lineno)
==> fprintf (stderr, "%s:%d: ", input_file, lineno)
And for that specific form, quoting further down in the page:
If your macro is complicated, you may want a more descriptive name for the variable argument than __VA_ARGS__. CPP permits this, as an extension. You may write an argument name immediately before the `...'; that name is used for the variable argument. The eprintf macro above could be written
#define eprintf(args...) fprintf (stderr, args)
Variable number of parameters. See variadic macros
It is a variadic macro.
A variadic macro is a macro that accepts a variable number of arguments. The feature has been introduced in C99.
The form
#define IDEBUG(a...) printf(a)
with the parameter a... is a GNU extension, a gives a name to the __VA_ARGS__ identifier.
The standard C99 form would be
#define IDEDBUG(...) printf(__VA_ARGS__)

How, exactly, does the double-stringize trick work?

At least some C preprocessors let you stringize the value of a macro, rather than its name, by passing it through one function-like macro to another that stringizes it:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
Example use cases here.
This does work, at least in GCC and Clang (both with -std=c99), but I'm not sure how it works in C-standard terms.
Is this behavior guaranteed by C99?
If so, how does C99 guarantee it?
If not, at what point does the behavior go from C-defined to GCC-defined?
Yes, it's guaranteed.
It works because arguments to macros are themselves macro-expanded, except where the macro argument name appears in the macro body with the stringifier # or the token-paster ##.
6.10.3.1/1:
... After the arguments for the
invocation of a function-like macro
have been identified, argument
substitution takes place. A parameter
in the replacement list, unless
preceded by a # or ## preprocessing
token or followed by a ##
preprocessing token (see below), is
replaced by the corresponding argument
after all macros contained therein
have been expanded...
So, if you do STR1(THE_ANSWER) then you get "THE_ANSWER", because the argument of STR1 is not macro-expanded. However, the argument of STR2 is macro-expanded when it's substituted into the definition of STR2, which therefore gives STR1 an argument of 42, with the result of "42".
As Steve notes, this is guarenteed, and it has been guarenteed since the C89 standard -- that was the standard the codified the # and ## operators in macros and mandates recursively expanding macros in args before substituting them into the body if and only if the body does not apply a # or ## to the argument. C99 is unchanged from C89 in this respect.

Resources