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__.
Related
I'm writing DEBUG_MSG for print debug messages
#define DEBUG_MSG(msg_str) _DEBUG_MSG_GENERIC(msg_str)
The _DEBUG_MSG_GENERIC is because I'd like to:
Show int message when a input parameter is int
Show char* message when a input parameter is char*
and its implement:
#define _DEBUG_MSG_GENERIC(strs) \
_Generic( (strs), \
int: _DEBUG_MSG_INT, \
default: _DEBUG_MSG_STR \
)(strs)
Now I'd like to implement _DEBUG_MSG_INT and _DEBUG_MSG_STR with Macro function and printf :
#define _DEBUG_MSG_INT(val) printf("%d\n", val);
#define _DEBUG_MSG_STR(str) printf("%s\n", str);
But I got error message is:
main.c:14:30: error: ‘_DEBUG_MSG_INT’ undeclared (first use in this function); did you mean ‘DEBUG_MSG’?
14 | int: _DEBUG_MSG_INT, \
| ^~~~~~~~~~~~~~
How do I solve it?
Does _generic only support function(pointer to function) and not support macro function?
Full Code
#include <stdio.h>
#define DEBUG_MSG(msg_str) _DEBUG_MSG_GENERIC(msg_str)
#define _DEBUG_MSG_GENERIC(strs) \
_Generic( (strs), \
int: _DEBUG_MSG_INT, \
default: _DEBUG_MSG_STR \
)(strs)
#define _DEBUG_MSG_INT(val) printf("%d\n", val)
#define _DEBUG_MSG_STR(str) printf("%s\n", str)
int main()
{
DEBUG_MSG("str");
DEBUG_MSG(5);
}
The problem is that both _DEBUG_MSG_INT and _DEBUG_MSG_STR are function-like macros thus they are only expanded if they are followed by ().
Note that macro expansion takes place before actual C compilation thus _Generic is nothing more than a common identifier at preprocessor stage.
I suggest using _Generic not for selection of the function pointer but rather for a formatting specifier to be used in printf(). Try:
#define _DEBUG_MSG_GENERIC(arg) printf( _DEBUG_MSG_FMTSPEC(arg), arg)
#define _DEBUG_MSG_FMTSPEC(arg) \
_Generic( (arg), int: "%d\n", default: "%s\n")
I believe your issue is because the preprocessor only makes one pass of the source code, so the printf's don't get substituted.
A quick solution would be to define _DEBUG_MSG_INT(val) and _DEBUG_MSG_STR(str) as real functions like so:
void _DEBUG_MSG_INT(int val) {
printf("%d\n", val);
}
void _DEBUG_MSG_STR(char * str) {
printf("%s\n", str);
}
The compiler will optimise out the extra function call overhead and will behave as if you called printf directly.
_Generic is not a preprocessor operation and cannot be used to select preprocessor macro functions. The code after a : in its cases must be a C expression (specifically an assignment-expression).
The code you have in those positions is _DEBUG_MSG_INT and _DEBUG_MSG_STR. Those are preprocessor macro names.
Those preprocessor macros are function-like macros. They are macro-replaced only when they are followed by a (. In your code, there is no ( after them, so they are not replaced.
That means the code after reprocessing looks like int : _DEBUG_MSG_INT,. So the compiler attempts to interpret _DEBUG_MSG_INT as an expression. Since _DEBUG_MSG_INT is not a declared identifier, the compiler reports an error that it is undeclared.
In summary, your code _Generic( (strs), int: _DEBUG_MSG_INT, default: _DEBUG_MSG_STR )(strs) attempts to use an after-preprocessing _Generic selection to select a preprocessing-time macro (either _DEBUG_MSG_INT or _DEBUG_MSG_STR) and then to have that macro treated as a function-like macros with the (strs) that appears after the _Generic. That simply cannot work; an after-preprocessing _Generic cannot select preprocessing macro names.
I bumped into the following macro while analyzing a code.
#define __COMMAND_HANDLER(name, extra ...) int name(struct command_invocation *cmd, ## extra)
The function name is passed as an argument to __COMMAND_HANDLER however there is no definition of this function anywhere else in the code. The cmd argument's type (command_invocation) is defined. Basically I couldn't understand the functionality of this macro because I couldn't find the definition of the function name. Is name some kind of pre-defined function in standard C library ? Does this macro definition make sense if name is not defined ?
Durning preprocession, the preprocessor will replace all occurrences of __COMMAND_HANDLER(name, extra ...) macro to its body with replacing each occurences of name and extra... inside its body to the tokens you specified.
This means in this case that whatever you enter for name argument, it will be a function name, and extra... will be its additional parameters beside the first one (struct command_invocation *cmd).
For example the following line:
__COMMAND_HANDLER(foo, int param) {
/* definition */
}
after preprocessing will be:
int foo(struct command_invocation *cmd, int param) {
/* definition */
}
One important thing has to be clarified: the ## before extra and named variable argument (using extra... instead of ...) are not the part of the c standard but they are GNU extensions. The effect of ## after comma lets you specify nothing for variable argument. Compiling your example with GCC (with -pedantic flag) when it's used as follows, you will see warning messages:
/* The following example will print the following messages:
* warning: ISO C does not permit named variadic macros [-Wvariadic-macros]
* warning: ISO C99 requires at least one argument for the "..." in a variadic
* macro
*/
__COMMAND_HANDLER(bar);
Normally the ## is the operator for token concatenation, i.e. two tokens on either side of a ## operator are combined into a single one. For example:
#include <stdio.h>
#define FOO(name, number) void name##number()
FOO(bar, 1) { puts("I'm first."); }
FOO(bar, 2) { puts("I'm second."); }
int main() {
bar1();
bar2();
return 0;
}
This is a macro and name is a parameter.
You use it like this:
__COMMAND_HANDLER(hello, char* world)
During pre-process stage, it would transform your code into:
int hello(struct command_invocation *cmd, char *world);
In this case, name is passed as hello, and extra = char* world.
If you don't pass anything for extra, ## will discard the comma.
In short: the macro is creating the function with the name specified by the parameter name and optional additional arguments specified by extra ....
Note: names starting with a double underscore is implementation reserved and shouldn't be used.
The macro is variadic.
The second argument to the macro extra ... provides a name to use instead of the default __VA_ARGS__ inside the function declaration macro. This is a GNU extension
## extra is another GNU extension that specifies to the preprocessor that if the second argument to the macro __COMMAND_HANDLER is omitted, the preceding comma can be removed and the function called without it.
The reason you can't find the declaration of name is because it's a parameter to your macro! The macro itself is declaring a new function with whatever is in name, and the arguments provided, with the default first argument of struct command_invocation *cmd.
Here are some examples:
Calling:
__COMMAND_HANDLER(cmd,char * w)
Would result in the function declaration of:
int cmd(struct command_invocation *cmd,char * w)
Whereas calling:
__COMMAND_HANDLER(cmd2)
would result in the function declaration of:
int cmd2(struct command_invocation *cmd)
I want to tokenize and strize, with macros, the name of the function we are in, to overload the function (with dlopen()), in C.
I found similar things with __LINE__ and __FILE__, but it seems to be a bit different in the case with __func__...
I tried that:
#define OVERLOAD2(f) printf("Trying to overload function %s...", #f)
#define OVERLOAD1(f) OVERLOAD2(f)
#define OVERLOAD OVERLOAD1(__func__)
int main() {
OVERLOAD;
}
Compiling with different standards of compilation (c99, gnu11) doesn't change the result; instead of printing:
Trying to overload function main...
It prints:
Trying to overload function __func__...
How can I correct those macros?
Here is what the C11 draft says about __func__:
1 The identifier __func__ shall be implicitly declared by the
translator as if, immediately following the opening brace of each
function definition, the declaration
static const char __func__[] = "function-name";
As you see __func__, unlike __FILE__ and __LINE__, is no preprocessor macro, so you can't evaluate it during the preprocessing stage.
But in your code, you don't even need to do that. Just change
#define OVERLOAD2(f) printf("Trying to overload function %s...", #f)
to
#define OVERLOAD printf("Trying to overload function %s...", __func__)
as you can see in the standard's description of __func__, it's already a string. No need to stringize it.
If you need the function name as a "bare word" at compile time, e.g. an implicit #define __FUNC__ myfunc, you're out of luck.
It's not possible in standard C. GCC additionally provides __FUNCTION__, but despite its all-caps name, the GCC manual says:
Neither of them is a macro; the preprocessor does not know the name of
the current function.
MSVC provides __FUNCTION__ as a macro but it's defined to a string and you can't strip away the double quotes.
Only way around that is writing your own preprocessor or rethink your approach
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 ().
I'd like to write a C macro which takes this:
int foo() {
MY_MACRO
}
and expands it to this:
int foo() {
_macro_var_foo++;
}
I've found that I can't use __func__, because that doesn't actually get expanded in the macro; it's treated by the preprocessor like a variable.
Is there some way to get this to work?
The preprocessor doesn't know about functions, just source files and line numbers. At that stage it's not performing syntactical analysis, just textual analysis and substitutions. That's why __func__ is a magical variable instead of a magical macro like __FILE__ and __LINE__.
In the C99 standard, __func__ is given a special new category of 'predefined identifier' (in section 6.4.2.2 Predefined Identifiers):
The identifier __func__ shall be implicitly declared by the translator as if,
immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function
This means that it is out of the scope of the C preprocessor, which is not aware of function boundaries or function names. Further, it would expand to a string, which makes it inappropriate for embedding into a variable name.
The GCC (4.4.1) manual says in section 5.43 (Function Names as Strings):
These identifiers [meaning __func__, __FUNCTION__ and __PRETTY_FUNCTION__] are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used
to initialize char arrays, and they could be concatenated with other string literals. GCC
3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.
If there was a way to get the function name into a preprocessor cleanly, then it is probable that the documentation here would have cross-referenced it, if it did not define it.
Technically, the answer to your question is "yes", there is "some way". But I think you already knew that, and it's true that you cannot deal with this at the macro preprocessor level.
Sure, there is always a way, you just might need a really long tape on that Turing Machine.
I think you already know this, but for the record you can get the overall result you want with:
#define MY_MACRO f_dictionary(__func__, ADDONE);
So now, you just need to implement f_dictionary and an ADDONE op for it.
You can do this using token concatenation.
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_WRAPPER(bar)\
int bar()\
{\
MY_MACRO(bar)\
}
FUNC_WRAPPER(foo)
The output from gcc -E:
int foo(){ _macro_var_foo++;}
Version dealing with argument lists using variadic macros and x macros:
#define MY_MACRO(baz) _macro_var_##baz++;
#define FUNC_DEF(ret_type,bar,...)\
ret_type bar(__VA_ARGS__)\
{\
MY_MACRO(bar)\
FUNC_CONTENTS\
}
#define FUNC_CONTENTS\
printf("Do some stuff\n", s1, s2);
FUNC_DEF(int, foo, char *s1, char *s2)
#undef FUNC_CONTENT