• <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ù)值類(lèi)型所對(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í)訪(fǎng)問(wèn)函數(shù)的名稱(chēng),直到不久前,唯一能完成此 項(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)換單元名稱(chēng)及當(dāng)前時(shí)間的字符串。
               在最新的ISO C標(biāo)準(zhǔn)中,如大家所知的C99,加入了另一個(gè)有用的、類(lèi)似宏的表達(dá)式__func__,其會(huì)報(bào)告未修飾過(guò)的(也就是未裁剪過(guò)的)、正在被訪(fǎng)問(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的用戶(hù)也應(yīng)使用 __FUNCTION__ ,而不是 __func__ 。
              C++ BuilderX的用戶(hù)則應(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ù)列表、返回類(lèi)型、內(nèi)含的命名空間組成。假如它是一個(gè)成員函數(shù),它的類(lèi)名和const/volatile限定符也將是簽名的 一部分。以下的代碼演示了一個(gè)獨(dú)立的函數(shù)與一個(gè)const成員函數(shù)簽名間的不同之處,兩個(gè)函數(shù)的名稱(chēng)、返回類(lèi)型、參數(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 多彩人生 閱讀(373) 評(píng)論(0)  編輯 收藏 引用


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


            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類(lèi)

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            一本色道久久综合亚洲精品| 久久久久99精品成人片试看| 国产69精品久久久久9999APGF| 亚洲精品tv久久久久久久久久| 国产亚洲色婷婷久久99精品91| 亚洲国产精品无码久久98| 国产精自产拍久久久久久蜜| 久久综合九色综合97_久久久 | 久久久久亚洲爆乳少妇无| 国产精品18久久久久久vr| 国产情侣久久久久aⅴ免费| 国产精品久久亚洲不卡动漫| 久久精品一本到99热免费| 国产精品成人久久久| 亚洲国产精品无码久久一区二区 | 久久精品夜色噜噜亚洲A∨| 久久久久久av无码免费看大片| 99久久国语露脸精品国产| 亚洲狠狠婷婷综合久久蜜芽| 无码人妻精品一区二区三区久久| 亚洲综合熟女久久久30p| 2020久久精品亚洲热综合一本| 久久精品国产久精国产一老狼| 精品无码久久久久久午夜| 无码伊人66久久大杳蕉网站谷歌| 久久精品中文騷妇女内射| 99re这里只有精品热久久| 2020最新久久久视精品爱| 2021国内精品久久久久久影院| 波多野结衣AV无码久久一区| 亚洲国产精品无码久久一区二区| 久久国产亚洲精品麻豆| 伊人精品久久久久7777| 无码国内精品久久人妻| 青青草原1769久久免费播放| 亚洲国产成人久久综合碰| 久久成人国产精品| 久久久久亚洲?V成人无码| 亚洲午夜久久久影院伊人| 国内精品久久久久久中文字幕| 久久免费看黄a级毛片|