• <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>

            風(fēng)雨兼程

            ring my bells
            posts - 49, comments - 14, trackbacks - 0, articles - 0

            回調(diào)機(jī)制

            Posted on 2009-06-15 22:31 silentneil 閱讀(544) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): C/C++
            過(guò)程語(yǔ)言中的回調(diào)(C)

            函數(shù)指針
            回調(diào)在C語(yǔ)言中是通過(guò)函數(shù)指針來(lái)實(shí)現(xiàn)的,通過(guò)將回調(diào)函數(shù)的地址傳給被調(diào)函數(shù)從而實(shí)現(xiàn)回調(diào)。因此,要實(shí)現(xiàn)回調(diào),必須首先定義函數(shù)指針,請(qǐng)看下面的例子:
            void Func(char *s);// 函數(shù)原型
            void (*pFunc) (char *);//函數(shù)指針


            可以看出,函數(shù)的定義和函數(shù)指針的定義非常類(lèi)似。

            一般的化,為了簡(jiǎn)化函數(shù)指針類(lèi)型的變量定義,提高程序的可讀性,我們需要把函數(shù)指針類(lèi)型自定義一下。

            typedef void(*pcb)(char *);


            回調(diào)函數(shù)可以象普通函數(shù)一樣被程序調(diào)用,但是只有它被當(dāng)作參數(shù)傳遞給被調(diào)函數(shù)時(shí)才能稱(chēng)作回調(diào)函數(shù)。

            被調(diào)函數(shù)的例子:

            void GetCallBack(pcb callback)
            {
            /*do something*/
            }

            用戶(hù)在調(diào)用上面的函數(shù)時(shí),需要自己實(shí)現(xiàn)一個(gè)pcb類(lèi)型的回調(diào)函數(shù):

            void fCallback(char *s) 
            {
            /* do something */
            }
             

            然后,就可以直接把fCallback當(dāng)作一個(gè)變量傳遞給GetCallBack,

            GetCallBack(fCallback);


            如果賦了不同的值給該參數(shù),那么調(diào)用者將調(diào)用不同地址的函數(shù)。賦值可以發(fā)生在運(yùn)行時(shí),這樣使你能實(shí)現(xiàn)動(dòng)態(tài)綁定。

            參數(shù)傳遞規(guī)則
            到目前為止,我們只討論了函數(shù)指針及回調(diào)而沒(méi)有去注意ANSI C/C++的編譯器規(guī)范。許多編譯器有幾種調(diào)用規(guī)范。如在Visual C++中,可以在函數(shù)類(lèi)型前加_cdecl,_stdcall或者_(dá)pascal來(lái)表示其調(diào)用規(guī)范(默認(rèn)為_(kāi)cdecl)。C++ Builder也支持_fastcall調(diào)用規(guī)范。調(diào)用規(guī)范影響編譯器產(chǎn)生的給定函數(shù)名,參數(shù)傳遞的順序(從右到左或從左到右),堆棧清理責(zé)任(調(diào)用者或者被調(diào)用者)以及參數(shù)傳遞機(jī)制(堆棧,CPU寄存器等)。

            將調(diào)用規(guī)范看成是函數(shù)類(lèi)型的一部分是很重要的;不能用不兼容的調(diào)用規(guī)范將地址賦值給函數(shù)指針。例如:


            // 被調(diào)用函數(shù)是以int為參數(shù),以int為返回值
            __stdcall int callee(int);

            // 調(diào)用函數(shù)以函數(shù)指針為參數(shù)
            void caller( __cdecl int(*ptr)(int));

            // 在p中企圖存儲(chǔ)被調(diào)用函數(shù)地址的非法操作
            __cdecl int(*p)(int) = callee; // 出錯(cuò)

             

            指針p和callee()的類(lèi)型不兼容,因?yàn)樗鼈冇胁煌恼{(diào)用規(guī)范。因此不能將被調(diào)用者的地址賦值給指針p,盡管兩者有相同的返回值和參數(shù)列


            例子:

            #include <stdio.h>
            void Func(char *);  //Function prototype
            void (*pFunc)(char *);  //Function pointer

            typedef 
            void(*pcb)(char *);

            void GetCallBack(pcb callback)
            {
                    
            /*do something*/
                    callback(
            "liangyi");
                    printf(
            "callback is diaoyonged\n");
            }


            void fCallback(char *a)
            {
                    
            /*do something*/
                    printf(a);
            }


            int main(void)
            {
                GetCallBack(fCallback);
            }



            參考自 http://m.shnenglu.com/jjbird/articles/3364.html 

            久久国产精品波多野结衣AV| 国内精品久久久久久久涩爱| 97久久综合精品久久久综合| 爱做久久久久久| 久久精品国产亚洲AV蜜臀色欲| 人妻久久久一区二区三区| 91精品日韩人妻无码久久不卡 | 亚洲国产精久久久久久久| 老司机午夜网站国内精品久久久久久久久| 久久午夜夜伦鲁鲁片免费无码影视 | 亚洲伊人久久成综合人影院| 无码久久精品国产亚洲Av影片| 久久中文娱乐网| 久久久婷婷五月亚洲97号色| 日韩美女18网站久久精品| 久久99毛片免费观看不卡| 性做久久久久久久久浪潮| 国产精品激情综合久久| 国产成人精品免费久久久久| 久久人与动人物a级毛片| 久久国产成人午夜AV影院| 久久青草国产手机看片福利盒子| 中文字幕热久久久久久久| 亚洲七七久久精品中文国产| 热久久这里只有精品| 精品久久777| 97久久精品人妻人人搡人人玩| 久久毛片一区二区| 漂亮人妻被中出中文字幕久久| 久久97久久97精品免视看秋霞 | 国产精品久久久久久福利漫画| 久久夜色精品国产噜噜噜亚洲AV| 热99RE久久精品这里都是精品免费| 久久亚洲色一区二区三区| 久久久久亚洲AV成人网| 精品久久人人妻人人做精品 | 激情伊人五月天久久综合| 亚洲AV日韩精品久久久久| 人妻精品久久无码专区精东影业| 日产精品久久久一区二区| 嫩草伊人久久精品少妇AV|