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.
Related
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; #
}
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
The LINE macro gives random number and FILE macro gives a null when, the "printf" is defined with another macro. In the following code, I have shown the macro used for "printf" and the function (which is a method of a class), where the macro is used:
#define OTConsolePrint(x) printf(x)
...
void parseArray(float* arr)
{
if (arr == NULL)
{
printf("Line: %d\n", __LINE__);
OTConsolePrint("Null pointer at \nLine: %d\nFile: %s\n", __LINE__, __FILE__);
}
}
gives me:
Line: 39
Null pointer at
Line: 1964696
File: (null)
#define OTConsolePrint(x, y, z) printf(x, y, z)
When you call the macro in the function you pass three elements.
Your "macro-function" takes just one argument:
#define OTConsolePrint(x) printf(x)
You call it, instead, with more than one argument:
OTConsolePrint("Null pointer at \nLine: %d\nFile: %s\n", __LINE__, __FILE__);
Actually I don't even think it compiles.
Anyway in order to have variadic argument you can do:
#define OTConsolePrint(STR, ...) printf(STR, __VA_ARGS__)
It works as expected.
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.
Let’s say there is a debugging function, simplified here as:
void DumpString(char* var, char* varname) {
printf("%s : '%s'\n", varname, var);
}
char str[10]="foobar";
DumpString(str, "str");
> str : foobar
Let’s make it easier by removing the unnecessarily extraneous requirement of passing the variable twice, once in quotes:
#define VARASSTR(v) #v
void DumpString(char* var) {
printf("%s : '%s'\n", VARASSTR(var), var);
}
char str[10]="foobar";
DumpString(str);
> var : foobar
Oops! It uses the local variable name instead of the one passed in. Let’s try a different (and less ideal) tack:
#define DumpStr(v) DumpString(v, #v)
void DumpString(char* var, char* varname) {
printf("%s : '%s'\n", varname, var);
}
char str[10]="foobar";
DumpStr(str);
> str : foobar
Great it works. But what if the function was a little more complicated:
void DumpString(char* var, char* varname, int optionalvar=0) {
printf("%s : '%s'\n", varname, var);
printf("blah: %d", optionalvar);
}
It is not possible to overload a macro, so DumpStr won’t work, and we have already ruled out the version with VARASSTR.
How can this be handled (without resorting to multiple similarly, but differently-named functions/macros)?
This is non-standard, but works as an extension in GNU C:
#define DumpStr(v, ...) DumpString(v, #v, ##__VA_ARGS__)
In GNU C, you can pass no arguments to a variadic macro, and the "token pasting operator" ## when applied between a comma and an empty variadic argument list produces nothing (so the trailing comma is suppressed).
In Visual C++, I believe the token pasting operator ## is unnecessary (and will probably break the macro), as Visual C++ automatically suppresses a trailing comma if it appears before an empty variadic argument list.
Note that the only thing that makes this nonstandard is the desire to sometimes pass an empty argument list. Variadic macros are standardized in both C99 and C++11.
Edit: And here's an example that doesn't use non-standard features. You can see why some people really, really wish this sort of thing was addressed in the standard:
#define DUMPSTR_1(v) DumpString(v, #v)
#define DUMPSTR_2(v, opt) DumpString(v, #v, opt)
#define DUMPSTR_NARG(...) DUMPSTR_ARG_N(__VA_ARGS__, 4, 3, 2, 1, 0)
#define DUMPSTR_ARG_N(_1, _2, _3, _4, n, ...) n
#define DUMPSTR_NC(f, ...) f(__VA_ARGS__)
#define DUMPSTR_NB(nargs, ...) DUMPSTR_NC(DUMPSTR_ ## nargs, __VA_ARGS__)
#define DUMPSTR_NA(nargs, ...) DUMPSTR_NB(nargs, __VA_ARGS__)
#define DumpStr(...) DUMPSTR_NA(DUMPSTR_NARG(__VA_ARGS__), __VA_ARGS__)
There's probably a few cleaner ways to do this. But not that many.
Edit 2: And here's yet another example that doesn't use non-standard features, courtesy of R..
#define STRINGIFY_IMPL(s) #s
#define STRINGIFY(s) STRINGIFY_IMPL(s)
#define ARG1_IMPL(a, ...) a
#define ARG1(...) ARG1_IMPL(__VA_ARGS__, 0)
#define DumpStr(...) DumpString(STRINGIFY(ARG1(__VA_ARGS__)), __VA_ARGS__)
Note that this requires the argument order of the DumpString to be changed so that the stringified function name is the first argument.