__LINE__ macro not working when define printf's macro - c++

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.

Related

Is it possible to make macros that are default arguments expand at call site?

#include <stdio.h>
void print(int a = __LINE__){printf("hello %d\n", a);}
void main(){
print();
print();
print();
print();
}
The __LINE__ macro in this case expands to 3, so the print function is called 4 times with the same value. Is there a way to convince the compiler to expand this macro at the callsite, so that the print function would be called with 6,7,8,9 instead of 3,3,3,3 with features that exist in C++11?
My usecase:
In my application, I provide multiple functions that take a unique ID. The ID should be unique per callsite/location (so if the function is called two times throught the same statement, it should receive the same id). Currently, the user always has to manually type a LOCATION macro at the callsite, like this:
#define S1(x) #x //voodoo to concat __FILE__ and __LINE__
#define S2(x) S1(x)
#define LOCATION __FILE__ S2(__LINE__)
do_stuff1(arguments, LOCATION)
do_stuff2(arguments, LOCATION)
It would be more convenient if I could save them the typing, without creating a macro for each function like this:
#define do_stuff1(do_stuff1_imp(arguments, LOCATION))
#define do_stuff2(do_stuff2_imp(arguments, LOCATION))
Hence I thought a default argument would do the trick. Is there any way to achieve this?
You seem to be looking for std::experimental::source_location, which will be std::source_location in a future standard:
#include <experimental/source_location>
void print(std::experimental::source_location const& location
= std::experimental::source_location())
{
printf("hello %s:%d\n", location.file_name(), location.line());
}
The __LINE__ macro in this case expands to 3
Sure because your function declaration is done at line 3 and the prepreprocessor expands it from there.
Another macro instead of a function declaration would do the trick well (taken from #Ejay's comment):
#define print() printf("hello %d\n", __LINE__)
See a working example here.
You can write a macro which inserts the __FILE__ and __LINE__ into the argument list:
// Note: this doesn't work with a 0-argument function. Supporting 0-arg functions
// is much harder to do; I'd recommend just having a separate macro like as follows
#define LOCATED(fn, ...) fn(__VA_ARGS__, __FILE__, __LINE__)
#define LOCATED0(fn) fn(__FILE__, __LINE__)
void print(char const* file_name, int line)
{
printf("hello %s:%d\n", file_name, line);
}
int do_something(int value, char const* file_name, int line);
int main() {
LOCATED0(print);
LOCATED(do_something, 42);
}
With a little more work, you can make it look nicer at the call-site:
#define LOCATED(...) LOCATED_##__VA_ARGS__
void print(char const* file_name, int line)
{
printf("hello %s:%d\n", file_name, line);
}
#define LOCATED_print() ::print(__FILE__, __LINE__)
int do_something(int value, char const* file_name, int line);
#define LOCATED_do_something(value) ::do_something(value, __FILE__, __LINE__)
int main() {
LOCATED(print());
LOCATED(do_something(42));
}

Stuck in understanding following macro definition

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; #
}

Different syntax for #define in C/C++ including many statements

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.

macro NAME expansion as string c/C++

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.

Passing variable name as string to function with default parameters

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.