Yes you can, but the macro substitution can get a little strange-looking. The double-macro substitution is there for a reason, and if you think about it for awhile, it will become clear why it is needed.
#define STRINGIZER_(exp) #exp
#define STRINGIZER(exp) STRINGIZER_(exp)
#define NUM 1234
int main(int argc, char *argv[])
{
const char *p = STRINGIZER(NUM);
printf("%s\n",p);
return EXIT_SUCCESS;
}
Running this:
1234
The reason for the double substitution: At first glance one may think this will solve the problem:
#define STRINGIZER(exp) #exp
#define NUM 1234
int main(int argc, char *argv[])
{
const char *p = STRINGIZER(NUM);
printf("%s\n",p);
return EXIT_SUCCESS;
}
But this produces:
NUM
which is not what we're trying to do. If you want the actual expansion of the NUM macro first then that is what you have to do: force the expansion. By forcing the preprocessor to substitute first through an intermediate expansion (as I show at the top of this answer) the passed-in macro is expanded first, then string-ized.
Side Bar: This technique is particularly useful for generating wide-char versions of predefined preprocessor macros that otherwise hold regular strings. For example, the __FILE__
macro. Suppose you wanted a wide-char version of this (a string prepended with 'L') You may first think this will work:
#define WIDESTR(str) L##str
but expanding this with __FILE__
as in:
const wchar *p = WIDESTR(__FILE__);
will result in a compiler error: "Undefined identifier: L__FILE__"
So how can we address this? The same way we did above.
#define WIDESTR_(str) L##str
#define WIDESTR(str) WIDESTR_(str)
int main(int argc, char *argv[])
{
const wchar_t* p = WIDESTR(__FILE__);
wcout << p << endl;
return EXIT_SUCCESS;
}
On my system, this produces:
/Users/craig/tmp/main/main/test.cpp
In Closing...
As a consolation prize, we combine everything in this answer into one giant goo-pile, what do we suppose happens when we do this:
int main()
{
const wchar_t *p = WIDESTR(STRINGIZE(NUM));
wcout << p << endl;
return EXIST_SUCCESS;
}