C++ 保存C+的原始值+;预处理宏

C++ 保存C+的原始值+;预处理宏,c++,macros,c-preprocessor,C++,Macros,C Preprocessor,我想保存宏的原始文本值,这样我就可以重新定义宏并仍然引用原始值。我的用例涉及一个宏到一个宏,因此我试图保存的值本身仍然是一个宏。我有一个在线解释器尝试的小例子,我从这里复制代码。我知道其他SO问题讨论了类似的想法,但我没有找到任何涵盖我的用例的内容 #include <stdio.h> #define STR(X) (#X) #define GLOBAL_INT (3) // I AM TRYING TO SAVE THE TEXTUAL MACRO CONTENT "GLOB

我想保存宏的原始文本值,这样我就可以重新定义宏并仍然引用原始值。我的用例涉及一个宏到一个宏,因此我试图保存的值本身仍然是一个宏。我有一个在线解释器尝试的小例子,我从这里复制代码。我知道其他SO问题讨论了类似的想法,但我没有找到任何涵盖我的用例的内容

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

将预处理器运算符应用于宏参数时,应添加额外级别的间接寻址(另一个宏),以便正确展开宏参数。使用令牌连接操作符来考虑这个例子(Sovia):

这是一个正在运行的示例

编辑:
您的代码是否通过应用此处解释的解决方案工作。请注意第二个输出是如何
GIM
,因为该宏未定义且
GIM
仅被视为令牌。

不可能。C/C++预处理器仅在求值时扩展宏。无法告诉它定义宏以扩展另一个宏的结果

也就是说,如果您使用了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;
}
(见附件)


如您所见,一旦定义了GIM,宏将停止扩展到“3”,但定义GIM时创建的字符串常量将保留该值。在这些宏中添加了所有括号。

也许
BOOST\u PP\u SLOT
?它只与整数数据AFAICR一起工作。这是标记C++,所以除非你与宏的编译时语义绑定,否则为什么不构建一个存储值历史的类(也使用<代码> STD::String ,IoFiels>>等)?@ CrasMSTR我与宏的编译时语义绑定。另外,我粘贴的代码试图保存值历史记录,但我发现我仍然无法保存预期值。@Crashmst另外,据我所知,将值保存在实际变量中只是出于诊断目的。我能保存宏的文本内容的唯一方法是将其保存为字符串,而据我所知,没有办法将该字符串内容注入到可以稍后调用的预处理器宏中。有些编译器允许使用可以推送和弹出宏/定义的杂注。对不起,但是我没有看到问题中的任何地方使用tokenpaste,也没有看到您将宏的扩展值(如问题所要求的)保存到任何地方。@JanHudec扩展问题完全适用于
#
操作符。这只是问题的一个例子,以及如何解决它。保存也完成了,因为(如果我没有错的话)问题只是没有正确扩展宏参数。这就是为什么我的示例包括一个
ID
宏和一个
FOO\u标识符(ID)
。请注意宏是如何展开的,并返回
foo_hello
而不是
foo_ID
。虽然问题确实出现在示例的第一部分中,但它似乎不是问题的要点。也可能是,但您需要使用问题中的代码来演示它。我不确定如何将此示例应用到我的示例中。我看到宏正在扩展到
foo_hello
,而不是
foo_ID
,但我不知道“hello”。如果我可以设置宏的原始值,那么保存宏会更容易。宏实际上最终扩展为一个外部函数,我正试图调用它。@taz注意
#define ID hello
,相当于您的
#define GIM(GLOBAL_INT)
。还可以看到第二个链接,其中包含已修复并正在运行的代码。考虑到此处和此处的信息(可能使用不平衡嵌套、递归技巧等),我仍然相信这是可能的@taz:不,不是。宏定义的右侧绝对不进行扩展,宏扩展无法生成新的
#define
指令。如果没有这两个选项,则无法定义宏
A
,该宏将包含宏
B
的值,即使在取消定义
B
之后也是如此。您必须将宏扩展为C/C++代码,而它所依赖的所有宏仍在定义中。当然,C++中有很多可以在一个地方声明并使用得很晚。@ JanHudec,您可能想检查Boost的完全标准兼容方式,以将一个宏定义为另一个扩展结果:(只适用于整数,但绝对有效,而且非常聪明)
#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
#define FOO_IDENTIFIER( id ) TOKEN_CAT( foo_ , id );
#define ID hello

int FOO_IDENTIFIER( ID ) = 0; // int foo_hello = 0;
#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;
}
strGimSave=(((3)))
gimSaveStr=((3))
strGimSaveM=(((3)))
gimStr=((3))

gim_save=(GIM)
gim_save_str=GIM
str_gim_save=(GIM)