|簡體中文

比思論壇

 找回密碼
 按這成為會員
搜索



查看: 385|回復: 0
打印 上一主題 下一主題

宏定义中的 "#" 和 "##" 的区别

[複製鏈接]

86

主題

3

好友

542

積分

中學生

Rank: 3Rank: 3

  • TA的每日心情
    開心
    2024-5-9 21:05
  • 簽到天數: 1593 天

    [LV.Master]伴壇終老

    推廣值
    0
    貢獻值
    0
    金錢
    7167
    威望
    542
    主題
    86
    樓主
    發表於 2014-11-14 21:28:04
    结果如下:
    "#" 代表和一个字符串相连接
    "##" 代表和一个符号连接,符号可以是变量,或另一个宏符号。
    举例如下:
    宏定义如下
    (1)
    #define DEV_FILE_NAME "/dev/test_kft"
    #define OPEN_FILE(fd, n) \
    { \
    fd = open(DEV_FILE_NAME #n,O_RDONLY); \
    if(fd
    预处理操作符'#'和'##'

    一,一般用法
    我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.
    用法:
    #include
    #include
    using namespace std;
    #define STR(s) #s
    #define CONS(a,b) int(a##e##b)
    int main(){
    printf(STR(vck)); // output vck
    printf("%d\n", CONS(2,3)); // 2000
    return 0;
    }
    二,当宏参数是另一个宏的时候
    但虽要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开.
    1, 非'#'和'##'的情况
    #define TOW (2)
    #define MUL(a,b) (a*b)
    printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
      这行的宏会被展开为 printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
      MUL里的参数TOW会被展开为(2).
    2, 当有'#'或'##'的时候
    #define A 2
    #define STR(s) #s
    #define CONS(a,b) int(a##e##b)
    printf("int max: %s\n", STR(INT_MAX)); // INT_MAX #include
      这行会被展开为printf("int max: %s\n", "INT_MAX");
    printf("%s\n", CONS(A, A)); // compile error
      这一行则是printf("%s\n", int(AeA));
      INT_MAX和A都不会再被展开,
    然而解决这个问题的方法很简单. 加多一层中间转换宏.
    #define A 2
    #define _STR(s) #s
    #define STR(s) _STR(s) // 转换宏
    #define _CONS(a,b) int(a##e##b)
    #define CONS(a,b) _CONS(a,b) // 转换宏
    printf("int max: %s\n", STR(INT_MAX)); // INT_MAX #include
    printf("%s\n", CONS(A, A));
    加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数.
    三,'#'和'##'的一些应用特例
    1, 合并匿名变量名
    #define ___ANONYMOUS1(type, var, line) type var##line
    #define __ANONYMOUS0(type,line) ___ANONYMOUS1(type, _anonymous, line)
    #define ANONYMOUS(type) __ANONYMOUS0(type,__LINE__)
    2,填充结构
    #define FILL(a) {a, #a}
    typedef struct MSG{
      int id;
      char* msg;
    }MSG;
    enum{OPEN,CLOSE};
    MSG _msg[]={FILL(OPEN),FILL(CLOSE)};
    3,记录文件名
    #define _GET_FILE_NAME(f) #f
    #define GET_FILE_NAME(f) _GET_FILE_NAME(f)
    static char FILE_NAME[]=GET_FILE_NAME(__FILE__);
    4,得到一个数值类型所对应的字符串缓冲大小
    #define _TYPE_BUF_SIZE(type) sizeof #type
    #define TYPE_BUF_SIZE(type) _TYPE_BUF_SIZE(type)
    char buf[TYPE_BUF_SIZE(INT_MAX)];
    itoa(2006, buf, 10);
    from: http://blog.vckbase.com/metaprogram/archive/2005/12/10/15823.aspx
    补充:
    1, "##"用于定义结构体类型.
       若结构体成员相同, 但是为了有所区别, 需要定义成不同的类型名, 此时用"##"就非常方便了. 比如, 定义一个用于调试的结构体类型:
        struct OperationResult_struct
        {
            int iRet;              //操作结果
            int iLine;             //行数
            char szFunc[256];      //函数名
            char szFile[512];      //文件名
        };
    但是我们想为Http的调试和文件操作的调试定义不同的类型名, 可以用如下方法.
        #define OPERATION_RESULT(name) \
        typedef struct name ##_struct \
        { \
           int iRet; \
           int iLint; \
           char szFunc[256]; \
           char szFile[512]; \
        }name
        OPERATION_RESULT(HttpResult);
        OPERATION_RESULT(FileResult);
        int main(int argc, char**argv)
        {
           HttpResult httpRet;
           FileResult fileRet;
        }
       用gcc -E 查看预编译结果.
    重要聲明:本論壇是以即時上載留言的方式運作,比思論壇對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,讀者及用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,讀者及用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本論壇受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者及用戶發現有留言出現問題,請聯絡我們比思論壇有權刪除任何留言及拒絕任何人士上載留言 (刪除前或不會作事先警告及通知 ),同時亦有不刪除留言的權利,如有任何爭議,管理員擁有最終的詮釋權。用戶切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。

    手機版| 廣告聯繫

    GMT+8, 2024-5-23 18:32 , Processed in 0.034076 second(s), 17 queries , Gzip On, Memcache On.

    Powered by Discuz! X2.5

    © 2001-2012 Comsenz Inc.

    回頂部