Disclaimer: I have already looked at the answers to questions similar to Stringification of a macro value.
Consider the following test program:
#include <stdio.h>
#define QUOTE(str) #str
#define EXPAND_AND_QUOTE(str) QUOTE(str)
#define MACRO HelloWorld
int main() {
printf("%s\n", EXPAND_AND_QUOTE(MACRO));
printf("%s\n", QUOTE(MACRO));
#undef MACRO
printf("%s\n", EXPAND_AND_QUOTE(MACRO));
printf("%s\n", QUOTE(MACRO));
}
The output of this program is:
HelloWorld
MACRO
MACRO
MACRO
The desired output is
HelloWorld
MACRO
MACRO
Is there a way to redefine my macros (that is, the meta-macros which are not MACRO) to get the desired output?
In particular, I want it to be the case that the third printf
should be equivalent to:
printf("%s\n", QUOTE());
That is, I want the expansion of the undefined macro into "nothingness" and then have that "nothingness" passed to the quote function.
This is not possible in standard C.
There are four things that can happen to a token during macro replacement. It can remain unchanged, it can be substituted with a replacement value, it can be concatenated with another token, and it can be stringized.
If MACRO
is unchanged, there is no way to distinguish these two situations:
#undef MACRO
printf("%s\n", EXPAND_AND_QUOTE(MACRO));
#define FOO MACRO
printf("%s\n", EXPAND_AND_QUOTE(FOO));
Once FOO
is replaced in the latter, we have two situations: In one, we have MACRO
because it is unchanged. In the other, we have MACRO
because it was substituted for FOO
. After that point, the behavior must be identical. But the problem requirements call for different behavior, ""
for the former and "MACRO"
for the latter. Since identical behavior cannot produce different results, this will not work. (But more about this below.)
The second possibility, substitution with another value, does not happen, since MACRO
is not defined.
The third possibility merely produces some new token, such as FOOMACRO
. However, although we can choose the first part, we cannot choose the latter part, so we cannot know what token will result, and there is nothing we might do with it that would differ depending on whether MACRO
is defined or not.
The fourth possibility has the same problem as the third, we produce "MACRO"
and can make no use of it.
The only vague hope I had of doing something with this is producing two tokens, one the result of letting the token be replaced and one not. E.g., we can produce a situation in which, given the above non-definition of MACRO
and the definition of FOO
, EXPAND_AND_QUOTE(MACRO)
produces, somewhere in a chain of expansions of helper macros, two tokens SomethingMACRO
and SomethingMACRO
, while EXPAND_AND_QUOTE(FOO)
produces SomethingFOO
and SomethingMACRO
. That is possible, but then what do we do with the two tokens? We could stringize both and then compare them with strcmp
at run time. However, I do not think anything can be done at compile time. Also, it would fail to distinguish the situation in which FOO
is defined as #define FOO FOO
; that would, if we were successful in comparing the tokens described above, produce ""
, but the requirements call for it to produce "FOO"
.
Try this:
#undef MACRO
#define MACRO
Alternatively:
#undef MACRO
#ifndef MACRO
# undef EXPAND_AND_QUOTE
# define EXPAND_AND_QUOTE(str) ""
#endif
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With