• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            c++ 宏

            c/c++ 宏中"#"和"##"的用法
            2007年05月14日 星期一 上午 10:19
            一、一般用法
            我們使用#把宏參數(shù)變?yōu)橐粋€(gè)字符串,用##把兩個(gè)宏參數(shù)貼合在一起.
            用法:
            #i nclude<cstdio>
            #i nclude<climits>
            using namespace std;
            #define STR(s)      #s
            #define CONS(a,b)   int(a##e##b)

            int main()
            {
                 printf(STR(vck));            // 輸出字符串"vck"
                 printf("%d\n", CONS(2,3));   // 2e3 輸出:2000
                 return 0;
            }

            二、當(dāng)宏參數(shù)是另一個(gè)宏的時(shí)候
            需要注意的是凡宏定義里有用'#'或'##'的地方宏參數(shù)是不會(huì)再展開(kāi).

            1, 非'#'和'##'的情況
            #define TOW       (2)
            #define MUL(a,b) (a*b)

            printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
            這行的宏會(huì)被展開(kāi)為:
            printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
            MUL里的參數(shù)TOW會(huì)被展開(kāi)為(2).

            2, 當(dāng)有'#'或'##'的時(shí)候
            #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 #i nclude<climits>
            這行會(huì)被展開(kāi)為:
            printf("int max: %s\n", "INT_MAX");

            printf("%s\n", CONS(A, A));                // compile error
            這一行則是:
            printf("%s\n", int(AeA));

            INT_MAX和A都不會(huì)再被展開(kāi), 然而解決這個(gè)問(wèn)題的方法很簡(jiǎn)單. 加多一層中間轉(zhuǎn)換宏.
            加這層宏的用意是把所有宏的參數(shù)在這層里全部展開(kāi), 那么在轉(zhuǎn)換宏里的那一個(gè)宏(_STR)就能得到正確的宏參數(shù).

            #define A            (2)
            #define _STR(s)      #s
            #define STR(s)       _STR(s)           // 轉(zhuǎn)換宏
            #define _CONS(a,b)   int(a##e##b)
            #define CONS(a,b)    _CONS(a,b)        // 轉(zhuǎn)換宏

            printf("int max: %s\n", STR(INT_MAX));           // INT_MAX,int型的最大值,為一個(gè)變量 #i nclude<climits>
            輸出為: int max: 0x7fffffff
            STR(INT_MAX) -->   _STR(0x7fffffff) 然后再轉(zhuǎn)換成字符串;

            printf("%d\n", CONS(A, A));
            輸出為:200
            CONS(A, A)   -->   _CONS((2), (2))   --> int((2)e(2))

            三、'#'和'##'的一些應(yīng)用特例
            1、合并匿名變量名
            #define   ___ANONYMOUS1(type, var, line)   type   var##line
            #define   __ANONYMOUS0(type, line)   ___ANONYMOUS1(type, _anonymous, line)
            #define   ANONYMOUS(type)   __ANONYMOUS0(type, __LINE__)
            例:ANONYMOUS(static int);   即: static int _anonymous70;   70表示該行行號(hào);
            第一層:ANONYMOUS(static int);   -->   __ANONYMOUS0(static int, __LINE__);
            第二層:                         -->   ___ANONYMOUS1(static int, _anonymous, 70);
            第三層:                         -->   static int   _anonymous70;
            即每次只能解開(kāi)當(dāng)前層的宏,所以__LINE__在第二層才能被解開(kāi);

            2、填充結(jié)構(gòu)
            #define   FILL(a)    {a, #a}

            enum IDD{OPEN, CLOSE};
            typedef struct MSG{
               IDD id;
               const char * msg;
            }MSG;

            MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
            相當(dāng)于:
            MSG _msg[] = {{OPEN, "OPEN"},
                           {CLOSE, "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、得到一個(gè)數(shù)值類型所對(duì)應(yīng)的字符串緩沖大小
            #define   _TYPE_BUF_SIZE(type)   sizeof #type
            #define   TYPE_BUF_SIZE(type)    _TYPE_BUF_SIZE(type)
            char   buf[TYPE_BUF_SIZE(INT_MAX)];
                  -->   char   buf[_TYPE_BUF_SIZE(0x7fffffff)];
                  -->   char   buf[sizeof "0x7fffffff"];
            這里相當(dāng)于:
            char   buf[11];

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            c和c++調(diào)式 利用宏獲得函數(shù)名
            僅僅為了獲取函數(shù)名,就在函數(shù)體中嵌入硬編碼的字符串,這種方法單調(diào)乏味還易導(dǎo)致錯(cuò)誤,不如看一下怎樣使用新的C99特性,在程序運(yùn)行時(shí)獲取函數(shù)名吧。
               對(duì)象反射庫(kù)、調(diào)試工具及代碼分析器,經(jīng)常會(huì)需要在運(yùn)行時(shí)訪問(wèn)函數(shù)的名稱,直到不久前,唯一能完成此 項(xiàng)任務(wù)并且可移植的方法,是手工在函數(shù)體內(nèi)嵌入一個(gè)帶有該函數(shù)名的硬編碼字符串,不必說(shuō),這種方法非常單調(diào)無(wú)奇,并且輕易導(dǎo)致錯(cuò)誤。本文將要演示怎樣使用 新的C99特性,在運(yùn)行時(shí)獲取函數(shù)名。
              那么怎樣以編程的方式從當(dāng)前運(yùn)行的函數(shù)中得到函數(shù)名呢?
              答案是:使用__FUNCTION__ 及相關(guān)宏。
              引出問(wèn)題
              通常,在調(diào)試中最讓人心煩的階段,是不斷地檢查是否已調(diào)用了特定的函數(shù)。對(duì)此問(wèn)題的解決方法,一般是添加一個(gè)cout或printf()——假如你使用C語(yǔ)言,如下所示:
            void myfunc()
            {
            cout<<"myfunc()"<<endl;
            //其他代碼
            }
            通常在一個(gè)典型的工程中,會(huì)包含有數(shù)千個(gè)函數(shù),要在每個(gè)函數(shù)中都加入一條這樣的輸出語(yǔ)句,無(wú)疑難過(guò)上“蜀山”啊,因此,需要有一種機(jī)制,可以自動(dòng)地完成這項(xiàng)操作。
              獲取函數(shù)名
              作為一個(gè)C++程序員,可能經(jīng)常碰到 __TIME__、__FILE__、__DATE__ ,__LINE__ 這樣的宏,它們會(huì)在編譯時(shí),分別轉(zhuǎn)換為包含編譯時(shí)間、處理的轉(zhuǎn)換單元名稱及當(dāng)前時(shí)間的字符串。
               在最新的ISO C標(biāo)準(zhǔn)中,如大家所知的C99,加入了另一個(gè)有用的、類似宏的表達(dá)式__func__,其會(huì)報(bào)告未修飾過(guò)的(也就是未裁剪過(guò)的)、正在被訪問(wèn)的函數(shù)名。請(qǐng) 注重,__func__不是一個(gè)宏,因?yàn)轭A(yù)處理器對(duì)此函數(shù)一無(wú)所知;相反,它是作為一個(gè)隱式聲明的常量字符數(shù)組實(shí)現(xiàn)的:
            static const char __func__[] = "function-name";
            在function-name處,為實(shí)際的函數(shù)名。為激活此特性,某些編譯器需要使用特定的編譯標(biāo)志,請(qǐng)查看相應(yīng)的編譯器文檔,以獲取具體的資料。
              有了它,我們可免去大多數(shù)通過(guò)手工修改,來(lái)顯示函數(shù)名的苦差事,以上的例子可如下所示進(jìn)行重寫(xiě):
            void myfunc()
            {
            cout<<"__FUNCTION__"<<endl;
            }
            官 方C99標(biāo)準(zhǔn)為此目的定義的__func__標(biāo)識(shí)符,確實(shí)值得大家關(guān)注,然而,ISO C++卻不完全支持所有的C99擴(kuò)展,因此,大多數(shù)的編譯器提供商都使用 __FUNCTION__ 取而代之,而 __FUNCTION__ 通常是一個(gè)定義為 __func__ 的宏,之所以使用這個(gè)名字,是因?yàn)樗咽艿搅舜蠖鄶?shù)的廣泛支持。
              在Visual Studio 2005中,默認(rèn)情況下,此特性是激活的,但不能與/EP和/P編譯選項(xiàng)同時(shí)使用。請(qǐng)注重在IDE環(huán)境中,不能識(shí)別__func__ ,而要用__FUNCTION__ 代替。
              Comeau的用戶也應(yīng)使用 __FUNCTION__ ,而不是 __func__ 。
              C++ BuilderX的用戶則應(yīng)使用稍稍不同的名字:__FUNC__ 。
              GCC 3.0及更高的版本同時(shí)支持 __func__ 和__FUNCTION__ 。
              一旦可自動(dòng)獲取當(dāng)前函數(shù)名,你可以定義一個(gè)如下所示顯示任何函數(shù)名的函數(shù):
            void show_name(const char * name)
            {
            cout<<name<<endl;
            }
            void myfunc()
            {
            show_name(__FUNCTION__); //輸出:myfunc
            }
            void foo()
            {
            show_name(__FUNCTION__); //輸出:foo
            }
            因?yàn)?__FUNCTION__ 會(huì)在函數(shù)大括號(hào)開(kāi)始之后就立即初始化,所以,foo()及myfunc()函數(shù)可在參數(shù)列表中安全地使用它,而不用擔(dān)心重載。
              簽名與修飾名
               __FUNCTION__ 特性最初是為C語(yǔ)言設(shè)計(jì)的,然而,C++程序員也會(huì)經(jīng)常需要有關(guān)他們函數(shù)的額外信息,在Visual Studio 2005中,還支持另外兩種非標(biāo)準(zhǔn)的擴(kuò)展特性:__FUNCDNAME__ 與 __FUNCSIG__ ,其分別轉(zhuǎn)譯為一個(gè)函數(shù)的修飾名與簽名。函數(shù)的修飾名非常有用,例如,在你想要檢查兩個(gè)編譯器是否共享同樣的ABI時(shí),就可派得上用場(chǎng),另外,它還能幫助 你破解那些含義模糊的鏈接錯(cuò)誤,甚至還可用它從一個(gè)DLL中調(diào)用另一個(gè)用C++鏈接的函數(shù)。在下例中,show_name()報(bào)告了函數(shù)的修飾名:
            void myfunc()
            {
            show_name(__FUNCDNAME__); //輸出:?myfunc@@YAXXZ
            }
            一 個(gè)函數(shù)的簽名由函數(shù)名、參數(shù)列表、返回類型、內(nèi)含的命名空間組成。假如它是一個(gè)成員函數(shù),它的類名和const/volatile限定符也將是簽名的 一部分。以下的代碼演示了一個(gè)獨(dú)立的函數(shù)與一個(gè)const成員函數(shù)簽名間的不同之處,兩個(gè)函數(shù)的名稱、返回類型、參數(shù)完全相同:
            void myfunc()
            {
            show_name(__FUNCSIG__); // void __cdecl myfunc(void)
            }
            struct S
            {
            void myfunc() const
            {
            show_name(__FUNCSIG__); //void __thiscall S::myfunc(void) const
            }
            };



            posted on 2012-06-28 16:10 多彩人生 閱讀(374) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            国产高潮国产高潮久久久| 久久综合丝袜日本网| 一级做a爰片久久毛片16| 99国产精品久久| 久久国产精品成人免费| 91精品国产91久久久久久青草 | 国产精品久久久久影院嫩草 | 激情综合色综合久久综合| 久久精品一区二区三区中文字幕 | 日本国产精品久久| 亚洲精品乱码久久久久久久久久久久 | 久久久久se色偷偷亚洲精品av| 久久精品国产亚洲AV香蕉| 精品久久国产一区二区三区香蕉| 亚洲另类欧美综合久久图片区| 亚洲AV日韩精品久久久久| 精品国产综合区久久久久久 | 久久免费精品视频| 久久精品中文字幕大胸| 狠色狠色狠狠色综合久久| 久久无码AV中文出轨人妻| 久久国产高清字幕中文| 伊人久久大香线蕉亚洲五月天 | 99久久成人18免费网站| 午夜精品久久久久久毛片| 久久播电影网| 国产成人综合久久精品尤物| 久久久久精品国产亚洲AV无码| 久久综合色区| 久久久久99精品成人片三人毛片| 精品999久久久久久中文字幕| 欧美丰满熟妇BBB久久久| 久久人人爽人人爽人人片av麻烦| 久久精品成人一区二区三区| 99麻豆久久久国产精品免费| 欧美午夜精品久久久久免费视| 久久只这里是精品66| 伊人情人综合成人久久网小说| 久久精品国产亚洲一区二区三区| 99久久婷婷国产综合精品草原| 久久er国产精品免费观看2|