• <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>
            posts - 16,  comments - 34,  trackbacks - 0

            題目有點(diǎn)繞口……

            問(wèn)題見(jiàn): http://bbs2.chinaunix.net/viewthread.php?tid=1373280

             

            問(wèn)題描述

             

            問(wèn)題解答

             


             

            問(wèn)題分析

            需要注意:
            I. 宏是作文本替換
            II. 替換的終止條件是:文件中不再含有宏

            對(duì)第9行的:SET_NAME(1212)
            1. 首先根據(jù)I和第5行,SET_NAME(1212) 會(huì)被替換成:CONNECTION(test,1212)
            2. CONNECTION依然是一個(gè)宏,根據(jù)II,繼續(xù)替換
            3. 根據(jù)I和第4行,CONNECTION(test,1212),被替換為 test1212
            4. 所以第10行最終會(huì)被CPP替換成 "int test1212 = 1212;"

            對(duì)第12行的:SET_NAME(VAR)
            1. 首先根據(jù)I和第5行,SET_NAME(VAR)會(huì)被替換成:CONNECTION(test,VAR)
            2. CONNECTIONVAR依然是一個(gè)宏,根據(jù)II,繼續(xù)替換
            3. 根據(jù)I和第11行,CONNECTION(test,VAR)被替換為CONNECTION(test,326)
            4. 再根據(jù)I和第4行,CONNECTION(test,326)被替換為test326
            5. 所以第12行最終會(huì)被CPP替換成 "int test326 = 326;"

            對(duì)第16行的:SET_NAME(VAR),同第12行,最終會(huì)被替換成 test86



            為什么setname不行?
            setname(var) 會(huì)被替換成 testvar,而后者不再含有宏,替換終止


             

            常見(jiàn)應(yīng)用

            根據(jù)行號(hào)命名——為了取一些相互不沖突的名字,使用行號(hào)作為后綴
            因?yàn)?span style="COLOR: #0000ff">__LINE__也是一個(gè),所以需要這種方法。

            例1,Loki::ScopeGuard

            Loki::ScopeGuard

             

            Loki::ScopeGuard MACRO 示例


             1// Loki::ScopeGuard macro sample
             2// Loki::ScopeGuard : 范型、輕量的RAII技術(shù) ,對(duì)資源管理與異常安全提供非常強(qiáng)大的支持
             3// 該處僅演示使用__LINE__作變量后綴名的方法, 暫不討論Loki::ScopeGuard
             4
             5#include <cassert>
             6#include <cstdio>
             7#include <stdexcept>
             8#include <string>
             9#include <loki::ScopeGuard>
            10
            11void CopyFile(const char* input_file,const char* output_file) /* throw(std::exception) */ {
            12    using namescape std;
            13
            14    FILE* input = fopen(input_file,"r");
            15    if (!input) throw runtime_error( string("can't open input file :"+ input_file);
            16    LOKI_ON_BLOCK_EXIT(fclose,input);
            17
            18    FILE* output = fopen(output_file,"wb");
            19    if (!output) throw runtime_error( string("can't open output file :"+ output);
            20    LOKI_ON_BLOCK_EXIT(fclose,output);
            21
            22    enum { buf_size = 1212 };
            23    char buf[buf_size];
            24    size_t r = buf_size;
            25
            26    do {
            27        r = fread(buf,1,buf_size,input);
            28        if ( buf_size != fwrite(buf,1,buf_size,output)
            29            throw runtime_error( string("write output file : "+ output + " occurs an error" );
            30    }

            31    while ( r == buf_size );
            32
            33    if ( !feof(input) {
            34        assert( ferror(input) );
            35        throw runtime_error( string("read input file : "+ input + " occurs an error");
            36    }

            37}

            38
            39
            40int main() {
            41    try 
            44    catch (std::exception& e) 
            47}

            48


             代碼中16和20行,根據(jù)loki/ScopeGuard.h (658)中的定義,將被分別替換成:

            ::Loki::ScopeGuard scopeGuard16 = ::Loki::MakeGuard(fclose,input);
            ::Loki::ScopeGuard scopeGuard20 
            = ::Loki::MakeGuard(fclose,output);

            也就是定義2個(gè)名字以scopeGuard為前綴文件行號(hào)為后綴的“變量”(名字就不會(huì)重復(fù))。
            它們?cè)?strong>退出作用域的時(shí)候會(huì)分別調(diào)用:fclose(input); fclose(output);
            PS:ScopeGuard的強(qiáng)大還不僅僅體現(xiàn)在這里,以后會(huì)專門介紹。


            例2.1,內(nèi)嵌匯編或者使用goto時(shí),需要一個(gè)不重復(fù)的跳轉(zhuǎn)標(biāo)號(hào)。

            make label



            例2.2,做鍵盤(pán)模擬的時(shí)候,按照i8042的規(guī)則,每次寫(xiě)入端口時(shí),需要等待輸入緩沖為空。
            所以需要實(shí)現(xiàn)一個(gè) KBC_Wait4IBE (key board controller wait for input buffer empty)



            但是又不想有函數(shù)調(diào)用消耗,所以打算用宏實(shí)現(xiàn)。
            實(shí)驗(yàn)1: 失敗的例子


            #define KBC_WAIT4IBE()  \
            KBC_WAIT4IBE_label:     \
            _asm in AL,64h      \
            _asm    TEST AL,10B \
            _asm    JNZ KBC_WAIT4IBE_label


            void KBC_KeyDown(byte scan) {
                KBC_WAIT4IBE(); // 等待輸入緩沖為空
                _outp(CMD_PORT,CMD_WRITE_OUTPUT_REG); // 準(zhǔn)備寫(xiě)入數(shù)據(jù)
                KBC_Wait4IBE(); // error C2045: 'KBC_WAIT4IBE_label' : label redefined
                // 標(biāo)號(hào)重復(fù)
            }


            有一個(gè)辦法就是給標(biāo)號(hào)加上行號(hào)作為后綴,那么在一個(gè)文件中也不會(huì)重復(fù)(使用 #line 除外……)。


            btw:上面那個(gè)函數(shù)實(shí)現(xiàn) KBC_Wait4IBE ,在VC8 release編譯下,會(huì)直接被inline,并且生成的代碼和KBC_WAIT4IBE完全相同……
            所以,要信任編譯器的優(yōu)化,不要無(wú)謂的犧牲可讀性~


            重要補(bǔ)充! 上述解釋并不準(zhǔn)確!!!
            setname(var) 中的var同樣是一個(gè)宏,為什么不被替換?
            SET_NAME(VAR)的第1次替換時(shí),同樣VAR沒(méi)有被替換,為什么第2次替換就會(huì)被替換?

            根據(jù)《代碼自動(dòng)生成-宏帶來(lái)的奇技淫巧》:http://www.shnenglu.com/kevinlynx/archive/2008/03/19/44828.html
            的說(shuō)法,第2次替換時(shí),涉及一個(gè)叫prescan的機(jī)制。
            我平時(shí)對(duì)CPP研究不多,所以也沒(méi)弄明白這個(gè)機(jī)制。硬盤(pán)里專門講C的書(shū)也不多,我翻翻看有沒(méi)有詳細(xì)介紹的……

            感興趣的讀者還可以參考: http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Macros.html



             

            再補(bǔ)充一點(diǎn): 關(guān)于于宏的調(diào)試。
            在MSVC下,可以給某個(gè)編譯單元xxx.c(cpp,cxx)加入"/P"(不含引號(hào),P一定大寫(xiě))命令。
            編譯該單元后,會(huì)在xxx.c的同目錄下生成xxx.i,即預(yù)處理的結(jié)果。
            在GCC下,可以使用 gcc(g++) -E xxx.c(cpp,cxx) (必要時(shí)還需要 -i ),查看預(yù)處理結(jié)果。



            再次補(bǔ)充

            在《The C Programming Language》 2nd Edition中找到了解釋
            附錄A.12.3 Macro Definition and Expansion p207。
            以下只摘錄重點(diǎn)部分:
            During collection(指第1次), arguments are not macro-expanded.
            In both (指帶參數(shù)或者不帶參數(shù))kinds of macro, the replacement token sequence is repeatedly rescanned for more defined identifiers.


            沒(méi)能搜到ANSI C標(biāo)準(zhǔn)的文檔……

            posted on 2009-02-18 23:59 OwnWaterloo 閱讀(3492) 評(píng)論(4)  編輯 收藏 引用

            FeedBack:
            # re: 使用宏作宏參數(shù)
            2009-02-19 09:25 | 飄雪
            好文,我原來(lái)對(duì)這個(gè)問(wèn)題也想了很久  回復(fù)  更多評(píng)論
              
            # re: 使用宏作宏參數(shù)
            2009-02-19 09:52 | 路青飛
            我可不可理解為,宏中宏!
            哈哈!好文!贊一個(gè)!  回復(fù)  更多評(píng)論
              
            # re: 使用宏作宏參數(shù)
            2009-02-19 11:50 |
            不錯(cuò),終于明白這個(gè)問(wèn)題了!當(dāng)初困擾我很久,還是沒(méi)有解決的問(wèn)題!哈哈  回復(fù)  更多評(píng)論
              
            # re: 使用宏作宏參數(shù)
            2010-05-10 17:05 | PattersonGay
            That is good that we are able to receive the <a href="http://lowest-rate-loans.com/topics/home-loans">home loans</a> and that opens new opportunities.   回復(fù)  更多評(píng)論
              
            # re: 使用宏作宏參數(shù)
            2010-08-08 14:31 | ringtone
            Any human in the our world wants to stay original, but does not know the correct way to do it. But thousands of different people look for the ringtones download or just composer ringtones to be unique.   回復(fù)  更多評(píng)論
              
            # re: 使用宏作宏參數(shù)
            2012-07-02 09:25 | on line essays
            To my mind, here only we receive the groundbreakingnewfangled brilliant data just about this good topic and that can be easygoing for men to buy term papers or buy an essay bestwritingservice.com from the professional custom essays writing firm.   回復(fù)  更多評(píng)論
              

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


            <2025年8月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            常用鏈接

            留言簿(8)

            隨筆檔案(16)

            鏈接

            搜索

            •  

            積分與排名

            • 積分 - 198662
            • 排名 - 134

            最新隨筆

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久久人妻精品一区| 性欧美丰满熟妇XXXX性久久久 | 国产毛片欧美毛片久久久| 久久综合九色欧美综合狠狠| 久久婷婷国产麻豆91天堂| a级毛片无码兔费真人久久| 久久综合九色欧美综合狠狠| 精品久久久久久无码人妻热 | 久久夜色精品国产欧美乱| 无码日韩人妻精品久久蜜桃 | 久久青青草视频| 久久久亚洲欧洲日产国码aⅴ| 成人妇女免费播放久久久| 国产精品久久久久久久久久影院 | 国内精品伊人久久久久影院对白| 99久久人人爽亚洲精品美女| 久久99精品久久久久久久久久| 亚洲狠狠综合久久| 久久精品天天中文字幕人妻| 国产成人久久精品一区二区三区| 精品久久久无码中文字幕天天| 国产精品久久久久久久久软件| 久久国产精品一区二区| 狠狠色狠狠色综合久久| 久久一区二区三区免费| 久久se精品一区精品二区| 亚洲国产精品无码久久久不卡| 久久久免费观成人影院| 国产精品久久久久久久久| 99久久综合国产精品免费| 久久精品国产99久久久香蕉| 99久久这里只精品国产免费| 精品少妇人妻av无码久久| 精品久久久久成人码免费动漫| 成人国内精品久久久久影院VR| 久久精品国产亚洲av麻豆色欲| 奇米影视7777久久精品人人爽| 久久综合给合综合久久| 精品人妻伦九区久久AAA片69 | 国产69精品久久久久777| 久久精品国产久精国产思思|