Reputation: 1526
I want to save the original textual value of a macro so that I can then redefine the macro and still refer to the original value. My use case involves a macro to a macro, so that the value I am trying to save is still itself a macro. I have a small example of attempts in an online interpreter, which I am copying the code from here. I am aware that other SO questions discuss similar ideas but I have not found anything that covers my use case.
#include <stdio.h>
#define STR(X) (#X)
#define GLOBAL_INT (3)
// I AM TRYING TO SAVE THE TEXTUAL MACRO CONTENT "GLOBAL_INT" (WITHOUT THE QUOTES)
// IN ANOTHER MACRO SO THAT I CAN UNDEFINE GIM AND STILL REFER TO GLOBAL_INT
#define GIM (GLOBAL_INT)
#define GIM_SAVE (GIM)
#define GIM_SAVE_STR (STR(GIM))
#define STR_GIM_SAVE (STR(GIM_SAVE))
const char *strGimSave = STR(GIM_SAVE);
const char *gimSaveStr = GIM_SAVE_STR;
const char *strGimSaveM = STR_GIM_SAVE;
const char *gimStr = STR(GIM);
#undef GIM
int main(int argc, char *argv[])
{
printf("strGimSave=%s\n", strGimSave);
printf("gimSaveStr=%s\n", gimSaveStr);
printf("strGimSaveM=%s\n", strGimSaveM);
printf("gimStr=%s\n", gimStr);
const char *gim_save = STR(GIM_SAVE);
const char *gim_save_str = GIM_SAVE_STR;
const char *str_gim_save = STR_GIM_SAVE;
printf("\ngim_save=%s\n", gim_save);
printf("gim_save_str=%s\n", gim_save_str);
printf("str_gim_save=%s\n", str_gim_save);
return 0;
}
Same code in online interpreter
Edit: I am trying to output "GLOBAL_INT" in the above code. The above code outputs:
strGimSave=GIM_SAVE
gimSaveStr=GIM
strGimSaveM=GIM_SAVE
gimStr=GIM
gim_save=GIM_SAVE
gim_save_str=GIM
str_gim_save=GIM_SAVE
Upvotes: 3
Views: 3451
Reputation: 76376
It is not possible. C/C++ preprocessor expands macros on evaluation only. There is no way to tell it to define macro to expanded result of another.
That said, the first part of your sample would actually do what you want if you used correct definition of STR:
#include <stdio.h>
// HERE, extra level of indirection
#define STR2(X) (#X)
#define STR(X) STR2(X)
#define GLOBAL_INT (3)
#define GIM (GLOBAL_INT)
#define GIM_SAVE (GIM)
#define GIM_SAVE_STR (STR(GIM))
#define STR_GIM_SAVE (STR(GIM_SAVE))
const char *strGimSave = STR(GIM_SAVE);
const char *gimSaveStr = GIM_SAVE_STR;
const char *strGimSaveM = STR_GIM_SAVE;
const char *gimStr = STR(GIM);
#undef GIM
int main(int argc, char *argv[])
{
printf("strGimSave=%s\n", strGimSave);
printf("gimSaveStr=%s\n", gimSaveStr);
printf("strGimSaveM=%s\n", strGimSaveM);
printf("gimStr=%s\n", gimStr);
const char *gim_save = STR(GIM_SAVE);
const char *gim_save_str = GIM_SAVE_STR;
const char *str_gim_save = STR_GIM_SAVE;
printf("\ngim_save=%s\n", gim_save);
printf("gim_save_str=%s\n", gim_save_str);
printf("str_gim_save=%s\n", str_gim_save);
return 0;
}
Now produces
strGimSave=(((3)))
gimSaveStr=((3))
strGimSaveM=(((3)))
gimStr=((3))
gim_save=(GIM)
gim_save_str=GIM
str_gim_save=(GIM)
(See live on coliru)
As you see once you #undef GIM
the macros stop expanding to "3", but the string constants created while GIM was defined retain the value. With all the parenthesis that you've put into those macros.
Upvotes: 5
Reputation: 14184
When applying preprocessor operators to macro argumments, you should add an extra level of indirection (Another macro) just to expand the macro argumments properly. Consider this example using the token concatenation operator (##
):
#define TOKEN_CAT_IMPL(x,y) x##x
#define TOKEN_CAT(x,y) TOKEN_CAT_IMPL(x,y) // <--- Here x and y are expanded before passed
Now you could use it for whatever you like:
#define FOO_IDENTIFIER( id ) TOKEN_CAT( foo_ , id );
#define ID hello
int FOO_IDENTIFIER( ID ) = 0; // int foo_hello = 0;
Here is a running example.
Here is your code working by applying the solution explained here. Note how the second outputs are GIM
, since that macro was undefined and GIM
was treated as a token only.
Upvotes: 2