How to print macro name in c or c++
eg:
#define APINAME abc
#define PRINTAPI(x) printf("x")
I want to print PRINTAPI(APINAME) and not "abc"
Macros are pre-processors and they will be replaced by their associated statement before compiling the code. So, you have no chance to have the macro names in run-time. But, you can generate the string name in compile-time:
#define APINAME abc
#define PRINTAPI(x) std::cout << #x << std::endl;
int main()
{
PRINTAPI(APINAME);
}
Output
APINAME
In macros the operator # makes the input parameter to a string literal (stringify)
Since macros disappear when the preprocessor is doing it's work, which happens before the compiler is called, the APINAME will not exist anywhere in the source code for the compiler to deal with. The only solution is to come up with some sort of connection between the two in some other way, e.g.
struct foo{
const char *name;
const char *val;
} myvar = { "APINAME", APINAME };
With a macro, you can do this in as a one-liner:
#define APINAME "abc"
#define APINAME_VAR(x, y) struct foo x = { #y, y }
APINAME_VAR(myvar, APINAME)
or
cout << "APINAME=" << APINAME << endl
printf("APINAME=%s\n", APINAME);
Or, in the case of your macro:
#define PRINTAPI printf("%s=%s\n", #APINAME, APINAME)
will print APINAME=abc
Related
#include <iostream>
#define MY_CONST 10
#define MY_OTHER_CONST MY_CONST
#undef MY_CONST
int main() {
enum my_enum : int {
MY_CONST = 100
};
std::cout << MY_OTHER_CONST;
return 0;
}
I would expect 10 as an output, but this program outputs 100. Can someone explain what is going on here?
https://godbolt.org/z/77EedG11x
#define MY_OTHER_CONST MY_CONST defines the macro MY_OTHER_CONST to have a replacement list of MY_CONST. No replacement is performed when defining a macro.
In std::cout << MY_OTHER_CONST;, MY_OTHER_CONST is replaced by its replacement list, becoming MY_CONST. At this point, there is no macro definition for MY_CONST, so no further replacement is performed. Then MY_CONST refers to the enum constant MY_CONST, which has value 100.
The 1 seems unnecessary (and possibly misleading) in the following example, but I have seen this multiple times when used for checking #ifdefs:
#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1
Is there a difference or reason for using the above versus a plain #define __NEWLIB_H__?
1 is true, so you can use the macro in an #if test. That's not usually very useful for header guards, but it certainly doesn't hurt. For other macros which might be tested in boolean expressions, the true value is definitely useful.
Some people just like the consistency. And that's the definition that gcc chooses by default if you put -D TESTME on the command line.
However,
#define __NEWLIB_H__ 1
is not cool unless it's in an implementation of the standard library, because names starting with two underscores (or an underscore and a capital letter) are reserved for use by the implementation, and should never be used in portable applications.
When used purely as an #include guard, there is no difference between
#ifndef __NEWLIB_H__
#define __NEWLIB_H__
and
#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1
However, in general, there is a distinction.
Compiler error
#ifndef ABCD
#define ABCD
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
Outputs the string "ABCD is 1"
#ifndef ABCD
#define ABCD 1
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
Outputs the string "ABCD is not 1"
#ifndef ABCD
#define ABCD 10
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
#define by itself will replace the symbol with nothing.
On the other hand, #define 1, as you call it, will replace the symbol with 1 everywhere it is found in the file. So, for example, the following code:
#include <iostream>
#define EXAMPLE "hello"
int main()
{
std::cout << EXAMPLE;
return 0;
}
prints
hello
This is because EXAMPLE here is replaced with "hello", making the print statement equivalent to:
std::cout << "hello";
If we change the #define statement to this instead:
#define EXAMPLE
This will give a compile error:
main.cpp: In function βint main()β:
main.cpp:15:25: error: expected primary-expression before β;β token
std::cout << EXAMPLE;
As to why you would ever use this second form of #define, it's because there is another processor directive that you can use called #ifdef:
#include <iostream>
#define EXAMPLE
int main()
{
#ifdef EXAMPLE
std::cout << "EXAMPLE defined.";
#endif
return 0;
}
This will print:
EXAMPLE defined.
Because #ifdef (and its relative #ifndef) only require that the symbol be defined, we don't really need to give it a value. It just needs to be there to work.
A common place you see this kind of stuff is with header guards (which is probably what you're seeing). You can also see it with platform identification, or even to determine whether the compiler is using C++ or not.
Is it possible to redefine a C++ #define macro using information from the macro itself? I tried the code below, but because of the way the macros are evaluated the output was not what I expected.
#include <iostream>
#define FINAL_DEFINE "ABC"
#define NEW_DEFINE FINAL_DEFINE "DEF" // Want ABCDEF
#undef FINAL_DEFINE
#define FINAL_DEFINE NEW_DEFINE // Want ABCDEF, but get empty?
int main ()
{
std::cout << FINAL_DEFINE << std::endl; // Want ABCDEF, but doesn't compile.
}
Macros in macro bodies are never expanded when the macro is defined -- only when the macro is used. That means that the definition of NEW_DEFINE is not "ABC" "DEF", it is exactly what appears on the #define line: FINAL_DEFINE "DEF".
So when you use FINAL_DEFINE, that gets expanded to NEW_DEFINE which then gets expanded to FINAL_DEFINE "DEF". At this point it will not recursively expand FINAL_DEFINE (as that would lead to an infinite loop) so no more expansion occurs.
If your compiler supports push_macro & pop_macro pragma directives, you could do this:
#include <iostream>
#define FINAL_DEFINE "ABC"
#define NEW_DEFINE FINAL_DEFINE "DEF"
int main ()
{
std::cout << FINAL_DEFINE << std::endl; // Output ABC
#pragma push_macro("FINAL_DEFINE")
#define FINAL_DEFINE "XXX"
std::cout << NEW_DEFINE << std::endl; // Output XXXDEF
#pragma pop_macro("FINAL_DEFINE")
}
After preprocessing all FINAL_DEFINE in the code will be replaced with the last thing it defined and then going to compiling step.
So you cannot redefine the macro like you want.
Your compiler should warn you about that.
Say I have a C macro-defined product version like this:
#define FOO_VERSION 1,0,0,1
And I want to print it at run-time:
#define STRING_VALUE(x) #x
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
This will output a string "FOO_VERSION", not "1,0,0,1". The macro
argument 'FOO_VERSION' is not replaced. So I try it again like
this:
#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(x) #x
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
It works, in Visual C++ 2013.
This is a cross-platform application although there are only five
lines of code. When I use clang to compile the code, a compile-
time error appears: "too many arguments provided to function-like
macro invocation". I guess the reason is the comma defined in
'FOO_VERSION'. So the third version:
#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(a, b, c, d) #a "," #b "," #c "," #d
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
This code works in clang, but Visual C++ will output a warning:
"not enough actual parameters for macro 'STRING_VALUE__'" at
compile-time, of course the run-time output is not right.
My question: is this pre-processor behavior defined ? Can I have a
universal version of STRING_VALUE macro ?
You can treat the argument as a single variadic macro:
#define FOO_VERSION 1,0,0,1
#define STRING_VALUE(...) STRING_VALUE__(__VA_ARGS__)
#define STRING_VALUE__(...) #__VA_ARGS__
This seems to work with gcc and Visual C++.
Can anyone tell when g++ replaces the __FUNCTION__ 'macro' with the string containing the function name? It seems it can replace it not until it has check the syntactical correctness of the source code, i.e. the following will not work
#include <whatsneeded>
#define DBG_WHEREAMI __FUNCTION__ __FILE__ __LINE__
int main(int argc, char* argv)
{
printf(DBG_WHEREAMI "\n"); //*
}
since after preprocessing using
g++ -E test.cc
the source looks like
[...]
int main(int argc, char* argv)
{
printf(__FUNCTION__ "test.cc" "6" "\n"); //*
}
and now the compiler rightly throws up because the *ed line is incorrect.
Is there any way to force that replacement with a string to an earlier step so that the line is correct?
Is __FUNCTION__ really replaced with a string after all? Or is it a variable in the compiled code?
Is there any way to force that replacement with a string to an earlier step so that the line is correct?
No. __FUNCTION__ (and its standardized counterpart, __func__) are compiler constructs. __FILE__ and __LINE__ on the other hand, are preprocessor constructs. There is no way to make __FUNCTION__ a preprocessor construct because the preprocessor has no knowledge of the C++ language. When a source file is being preprocessed, the preprocessor has absolutely no idea about which function it is looking at because it doesn't even have a concept of functions.
On the other hand, the preprocessor does know which file it is working on, and it also knows which line of the file it is looking at, so it is able to handle __FILE__ and __LINE__.
This is why __func__ is defined as being equivalent to a static local variable (i.e. a compiler construct); only the compiler can provide this functionality.
You are using __FUNCTION__ like a preprocessor macro, but it's a variable (please read http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html).
Try printf("%s", __FUNCTION__) just for testing and it will print the function name.
__FUNCTION__ is not standard. Use __func__. As the documentation says, it's as if:
<ret-type> function_name( <args> )
{
static const char __func__[] = "function-name";
...
In C/C++, the preprocessor will turn "my " "name " "is " "Bob" into the string literal "my name is Bob"; since __FILE__ and __LINE__ are preprocessor instructions, "We are on line " __LINE__ will pass "We are on line 27" to the compiler.
__FUNCTION__ is normally a synonym for __func__. __func__ can be thought of as a pseudo-function that returns the name of the function in which it is called. This can only be done by the compiler and not by the preprocessor. Because __func__ is not evaluated by the preprocessor, you do not get automatic concatenation. So if you are using printf it must be done by printf("the function name is %s", __func__);
Is this what you want?
#include <stdio.h>
#define DBG_WHEREAMI(X) printf("%s %s(%d): %s\n",__func__,__FILE__,__LINE__,X)
int main(int argc, char* argv)
{
DBG_WHEREAMI("Starting");
}
Note: Since you marked this as C++ you should probably be using the iostreams to make sure it's type safe.
printf("%s" __FILE__ __LINE__ "\n", __FUNCTION__);
Yeah, I know that's not really the same.
Note that if you create a class, you can build a message from any number of types as you'd like which means you have a similar effect to the << operator or the format in a printf(3C). Something like this:
// make sure log remains copyable
class log
{
public:
log(const char *function, const char *filename, int line)
{
f_message << function << ":" << filename << ":" << line << ": ";
}
~log()
{
//printf("%s\n", f_message.str().c_str()); -- printf?!
std::cerr << f_message.str() << std::endl;
}
log& operator () (const char *value)
{
f_message << value;
}
log& operator () (int value)
{
f_message << value;
}
// repeat with all the types you want to support in the base class
// (should be all the basic types at least)
private:
sstream f_message;
};
// start the magic here
log log_error(const char *func, const char *file, int line)
{
log l(func, file, line);
return l;
}
// NOTE: No ';' at the end here!
#define LOG_DEBUG log_error(__func__, __FILE__, __LINE__)
// usage sample:
LOG_DEBUG("found ")(count)(" items");
Note that you could declare the << operators instead of the (). In that case the resulting usage would be something like this:
LOG_DEBUG << "found " << count << " items";
Depends which you prefer to use. I kind of like () because it protects your expressions automatically. i.e. if you want to output "count << 3" then you'd have to write:
LOG_DEBUG << "found " << (count << 3) << " items";