Here is a macro definition:
#define print_debug(fmt, ...) \
__print_debug__(__FILE__, __func__, __LINE__, fmt, ## __VA_ARGS__)
I cannot locate the expansion of __FILE__,__func__ ,__LINE__ and ## __VA_ARGS__ in visual studio(I can get __VA_ARGS__ that corresponds to a variable arguments). In particular what dose ## __VA_ARGS__ mean?
__print_debug__ is a function like macro which will print all arguments passed to it.
Here
__FILE__ :--> will pass current File name
__func__:--> will pass current function name.
__LINE__ :--> will pass current line number
You can have a look at This Link for more information on it.
Now fmt and ## __VA_ARGS__ :
Let me take below example.
print_debug(fmt,var1,var2,var3)
the macro expansion will be as following:
__print_debug__(__FILE__, __func__, __LINE__, fmt,var1,var2,var3)
This is because ## will concatenate all the the variable list of argument i.e. __VA_ARGS__
Save following code in macro.c file and compile it with
gcc -E macro.c -o macro.i
command and have a look at the macro.i file.
#define print_debug(fmt, ...) \
__print_debug__(__FILE__, __func__, __LINE__, fmt, ## __VA_ARGS__)
void call_Macro()
{
print_debug(2,3,4,5) //Here 2 is nothing but fmt
}
int main()
{
call_Macro();
return 0; #
}
Related
I'm working with WPP (Windows Tracing) and the basic macro looks like this:
trace(SEVERITY, SOURCE, "%s started", app_name);
I would like to do is something like this but I get a variety of compiler/trace errors:
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
printf(__format, __VA_ARGS__); \
trace(__level, __flags, __format, ...); \
} while (false);
Is there a correct way to call the trace macro from the trace_with_console macro?
EDIT: Thank you everyone for replying. The problem isn't a macro issue, it is the WPP for Windows trace processor failing.
This tool parses the trace macro call and extracts the text to keep it secret, and replaces it with a GUID. You need debugging information to read the traces.
The processor gets confused by the trace macro being called within this context. At this stage it doesn't seem possible to do what I'm trying to do. #jxh answer works well, just not with WPP.
Thank you all again!
Without knowing anything about the trace() macro or function other than how you are trying to invoke it, I would rewrite your proposed macro as:
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
printf(__format, __VA_ARGS__); \
trace(__level, __flags, __format, __VA_ARGS__); \
} while (false)
Replace the ... in the call to trace with __VA_ARGS__ instead. The contents of the variable arguments represented by ... in your arg list for trace_with_console will be used in the expansion of __VA_ARGS__.
Remove the ; at the last line of your macro. This allows your macro to be treated as a statement that requires a ; at the end.
One disadvantage with the macro as it is written is that there are arguments that will be evaluated twice. Once evaluation will happen in the call to printf, and another evaluation in the call to trace.
Since __format and __VA_ARGS__ are being passed into printf, we assume trace can accept the same format specifications and corresponding arguments. Then, if there is a reasonable max size for your trace message, you may avoid multiple argument evaluation by using snprintf.
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
char __buf_for_trace[BUF_FOR_TRACE_MAX_SIZE]; \
snprintf(__buf_for_trace, sizeof(__buf_for_trace), \
__format, __VA_ARGS__); \
printf("%s", __buf_for_trace); \
trace(__level, __flags, "%s", __buf_for_trace); \
} while (false)
In C++, you can remove the macro and use a variadic template function instead.
template <typename LevelType, typename FlagsType, typename... Types>
void trace_with_console (
LevelType level, FlagsType flags,
const char *format, Type... args) {
printf(format, args...);
trace(level, flags, format, args...);
}
I am trying to write a debug macro in the common subset of C and C++. This is what I've come up with so far:
#define OUTPUT_ERROR(...) printf("%s(%d) : %s() : %s\n", __FILE__, __LINE__, __func__, #__VA_ARGS__)
Unfortunately, I cannot figure out how to give it variables to output. Is there any way to force a variable to be expanded at runtime? For example:
OUTPUT_ERROR("%s was broken", my_var);
or simply in place
OUTPUT_ERROR(my_var + "some text");
It seems to me that you're trying to cram too much into one printf() call. You don't need to do that. In particular, to support usage such as your first example:
OUTPUT_ERROR("%s was broken", my_var);
you could easily split the output over multiple printf() calls with a macro like this:
#define OUTPUT_ERROR(...) do { \
printf("%s(%d) : %s() : ", __FILE__, __LINE__, __func__); \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
I think you're looking to define a macro prepending some debugging information to your formatted log.
To achieve this, you can use the following macro :
#define LOG(format, ...) \
printf("%s(%d) : %s() " format, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
This way LOG("%d", 123) will expand to printf("%s(%d) : %s() " "%s", __FILE__, __LINE__, __FUNCTION__, 123).
As consecutive string literals are merged ("a" "b" is equivalent to "ab"), the printf format is correctly built.
Also note the use of , ## __VA_ARGS__. This is a GNU extension (see https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html) that allows empty variadic arguments.
This technique will however fail if format is not a string literal.
See an example here : http://ideone.com/gMnaES
I am trying to create a macro that would iterate over a defined list of terms, and for each invoke another macro, possibly with additional argument list. Here is what I have got:
#define ITERATE_OVER_TERMS(MACRO, ...) \
MACRO(Term1, __VA_ARGS__) \
MACRO(Term2, __VA_ARGS__) \
MACRO(Term3, __VA_ARGS__) \
... and so on
However, when I was trying to use it with Visual Studio 2015, i get an error
warning C4003: not enough actual parameters for macro 'BODY'
where BODY is the name of the macro passed as the MACRO argument. While technically a warning, it shows that something has gone wrong with the expansion.
In an attempt to narrow down the error, I reduced my example to the following:
#include <iostream>
#define ITERATE(MACRO, ...) \
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__)
#define BODY(IterationArg, Arg1, Arg2) \
std::cout << IterationArg << Arg1 << Arg2 << std::endl;
int main() {
ITERATE(BODY, 8, 9)
return 0;
}
It gives me the error as shown above, while I expected it to compile succesfully and produce the output
189
289
It does seem to compile with g++, but not Visual Studio.
What am I missing? Is there some walkaround for this to work?
The problem is that Visual Studio expands __VA_ARGS__ after they are being passed into a subsequent macro, and not before. This has caused problems in the past as well, for example here --
Why does this variadic argument count macro fail with VC++?
In your case, consider a simple change in the code:
#include <iostream>
#define ITERATE(MACRO, ...) \
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__)
#define BODY(IterationArg, Arg1, Arg2) \
std::cout << #Arg1 << std::endl;
int main() {
ITERATE(BODY, 8, 9)
return 0;
}
The argument #Arg1 is stringified, showing us its contents in the output:
8, 9
8, 9
Not what we expected, huh?
A solution is the same as in the linked question: force an expansion through a dummy EXPAND macro:
#define EXPAND(x) x
#define ITERATE(MACRO, ...) \
EXPAND(MACRO(1, __VA_ARGS__)) EXPAND(MACRO(2, __VA_ARGS__))
This gives you the desired result both in VS and gcc.
I understand the syntax of #define like,
#define Pi 3.14
So it's obvious that we can use Pi constant instead of 3.14 anywhere in code to make code more readable.
But I encountered a syntax like below.
Does it mean whenever I call the macro
doIT("hello world");
the code statements within {...} will be invoked ?
Does #define allow to give such syntax.?
What does the __FUNCTION__, __VA_ARGS__ mean ?
#define doIT(str, ...) \
{ \
if (pDoLog) pDoLog->LogMsg("[%s] Error: " str, LOG_WRONG, __FUNCTION__, ##__VA_ARGS__); \
printf("[%s] Error: " str "\n", __FUNCTION__, ##__VA_ARGS__); \
}
You don't "call" a macro, and its expansion doesn't get "invoked". The preprocessor just replaces the macro with its expansion, before the code gets compiled.
A macro defined with parentheses such as doIt(str) is a "function-like macro" which means it takes arguments which can be used in the expansion of the macro.
A function-like macro with ... in the argument list indicates it can accept a variable number of arguments. The special predefined symbol __VA_ARGS__ expands to the list of arguments passed to the ... placeholder.
__FUNCTION__ is a special predefined symbol that expands to the name of the current function being compiled, so wherever the macro gets expanded it will use the name of the enclosing function.
I want use the NAME of the macro inside the macro expansion as string.
Example:
#define DEBUG_TEST(a, ...) printf("DEBUG_TEST::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Want to change to something that doesn't need the "DEBUG_TEST" anymore in the exapansion, but something like:
#define DEBUG_TEST(a, ...) printf(__MACRO__ "::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Of course in my example __MACRO__ dosen't exist...
I believe this is not possible. My suggestion would be to create another macro that takes the name of the macro as argument. Then use this macro in your other macroses.