Macro with variable length of parameters - c

Is there a way to #define a macro with variable length of parameters?
#define CALL(ar1, ar2, ar3)
do something
#endif
in C code
CALL(0);
CALL(0,1);
CALL(0,1,2)
all invoke the above CALL macro. If ar2, ar3 not used, preprocessor just ignore the line with ar2 or ar3.

Yes, take a look at this one: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
Key word is __VA_ARGS__ ( Variadic Macros ):
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__)

Related

Access the contents of __VA_ARGS__ in a macro (not a function)

One can access the contents of ... inside a function using stdarg.h:
void fn(int nargs, ...){
va_list args; va_start(args,nargs);
i64 arg0 = va_arg(args,i64);
va_end(args);
}
The only way I know of using __VA_ARGS__ is to pass it to another macro or, eventually, a function. Eg.
#define __fn(...) fn(number_of_args(__VA_ARGS__), __VA_ARGS__)
but I wonder if it's possible to "unpack" the values of __VA_ARGS__ within a macro itself. Something like va_start(), va_arg(), and va_end(), but for macros.
if it's possible to "unpack" the values of VA_ARGS within a macro itself.
Yes, you can get the head #define HEAD(x, ...) x of the pack and iterate over the list with EVAL(EVAL(... recursive expansion. See https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms .
I find overloading on the number of macro arguments to produce way more readable error messages than EVAL(EVAL(.. expansions, so I prefer explicitly overloading for each argument.

Macro to call a function

I need a macro (or a function, but preferably a macro) that takes a function name and an unlimited number of arguments, then passes the arguments to the function. Let's say this macro is MACROFOO.
#define MACROFOO(function, ...) /* what do I put here?? */
int foo_bar(int x, int y)
{
// do stuff
}
int main(void)
{
int x = 3;
int y = 5;
MACROFOO(foo_bar, x, y); // calls foo_bar(x, y)
}
How could I define such a macro? I thought of doing something like:
#define MACROFOO(function, args...) (function)(args)
but it looks like that passes ... to the function, instead of the actual arguments. What should I do?
You can expand the ... of variadic macros with __VA_ARGS__.
Example:
#define MACROFOO(function, ...) (function)(__VA_ARGS__)
MACROFOO(printf, "hello world%c", '!')
/*^ expands to: (printf)("hello world%c", '!') */
Note: As you probably know, the parentheses prevent the function argument from being expanded as a macro (if it is a macro).
I.e.,
#define BAR(...) myprintf(__VA_ARGS__)
MACROFOO(BAR, "hello world%c", '!')
will expand to:
(BAR)("hello world%c", '!')
with the parentheses and
myprintf("hello world%c", '!')
if your remove them.
You can use either the standard variable argument __VA_ARGS__:
#define MACROFOO(function, ...) (function)(__VA_ARGS__)
or if you like a more descriptive name you can use this GNU CPP extension by writing a name immediately before ... :
#define MACROFOO(function, parameters...) (function)(parameters)
GNU CPP Section 3.6:
(...)
Variadic macros are a new feature in C99. GNU CPP has supported them
for a long time, but only with a named variable argument (‘args...’,
not ‘...’ and __VA_ARGS__).
If you are concerned with portability to
previous versions of GCC, you should use only named variable
arguments. On the other hand, if you are concerned with portability to
other conforming implementations of C99, you should use only
__VA_ARGS__.

how to concat a space with a symbol using c macro

#define var(N) variable ## N
var(1) got variable1
I want to get variable, how can I define the macro?
var( ) works, but it always give a warning. is there any other solutions?
In fact the version that you presented always needs a non-empty argument for N. If you have a modern C compiler you can use this construct:
#define var(...) variable ## __VA_ARGS__
This accepts empty arguments and you should be fine.
"modern" here means C as of 1999.
Don't use the argument inside the macro:
#define var(n) variable

Double slash comment substituition within a macro

I am developing a PIC MCU program on an ansi-compliant compiler (Microchip XC8).
There are two operation modes, determined via macros during compilation time.
So that I don't want to duplicate one function-like macro due to one line of code, I would like to know if there is any way to write a macro such as
#define FOO //
so that when FOO is substituted it will actually cancel the rest of the line.
Writing a function instead of a macro is out of the question because the delay generated by function calls would disrupt the tight timings of my program (around some microseconds).
You can't make a macro expand to comment out the line, no. // in a macro definition is a comment following the definition, it's not expanded, and IIRC there's a rule saying that you cannot construct a // using token-pasting. Even if you can, expanding it doesn't mean that the macro starts a comment. Basically, you don't get to change the comment syntax using macros.
You could do:
#if DO_NOTHING_MODE
#define FOO(ARG1)
#else
#define FOO(ARG1) ARG1
#endif
and use it like:
#define FUNCTION_LIKE_MACRO(ARG1, ARG2) \
required line; \
FOO(optional line;) \
Although a more common idiom is to design the macro to accept an expression as its argument, rather than a whole line:
#if DO_NOTHING_MODE
#define FOO(ARG1) ((void)0)
#else
#define FOO(ARG1) (ARG1)
#endif
and use it like FOO(optional line);
Either way, if the macro argument has commas in it, then the caller needs to enclose them in parentheses FOO((1,2)), although in C99 you can avoid that by making FOO a variadic macro:
#define FOO(...) (__VA_ARGS__)
You can use the #ifndef directive to achieve the same effect:
#ifndef FOO
your_line_of_code
#endif
EDIT: #SteveJessop made me see I didn't pay attention to this sentence of the OP "I don't want to duplicate one function-like macro due to one line of code". Here is what could be done in that case, if duplicating the function-like macro is not wanted:
// When FOO is defined, BLA in FUNC macro is a no-operation (null statement)
#ifndef FOO
#define BLA() a++
#else
#define BLA()
#endif
#define FUNC() \
BLA(); \
b++;
Comments are removed from the source before macro replacement occurs, so there's no way to define a macro exactly like that. However, it is certainly possible to pass an additional parameter into the macro to specify which code it should generate, or conditionally define the macro depending on the mode for which you are compiling.
#define FOO(...) __VA_ARGS__
And then use FOO(your code here) instead of FOO your code here in the macro.
If your platform doesn't have C99, you can instead use
#define FOO(x) x
and just make sure the argument doesn't contain a , not enclosed in ().

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

Resources