簡體   English   中英

保存C ++預處理程序宏的原始值

[英]Save original value of C++ preprocessor macro

我想保存宏的原始文本值,以便隨后可以重新定義宏並仍然引用原始值。 我的用例涉及到宏的宏,因此我要保存的值本身仍然是宏。 我有一個在線解釋器嘗試的小例子,我從這里復制代碼。 我知道其他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;
}

在線解釋器中的相同代碼

編輯:我試圖在上面的代碼中輸出“ GLOBAL_INT”。 上面的代碼輸出:

strGimSave=GIM_SAVE
gimSaveStr=GIM
strGimSaveM=GIM_SAVE
gimStr=GIM

gim_save=GIM_SAVE
gim_save_str=GIM
str_gim_save=GIM_SAVE

這是不可能的 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;
}

現在生產

strGimSave=(((3)))
gimSaveStr=((3))
strGimSaveM=(((3)))
gimStr=((3))

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

(請參閱coliru上的直播

如您所見,一旦#undef GIM宏停止擴展到“ 3”,但是在定義GIM時創建的字符串常量將保留該值。 加上您在這些宏中添加的所有括號。

將預處理器運算符應用於宏對象時,應添加一個額外的間接級別(另一個宏),以適當地擴展宏對象。 考慮使用令牌級聯運算符( ## )的示例:

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

是一個正在運行的示例。

編輯:

是通過應用此處說明的解決方案來工作的代碼。 請注意第二個輸出是GIM ,因為該宏未定義並且GIM僅被視為令牌。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM