• <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://www.shnenglu.com/jjbird/articles/3364.html 

            亚洲国产成人久久综合碰| 狠狠色综合久久久久尤物| 久久久黄片| 亚洲伊人久久大香线蕉苏妲己| 无码人妻精品一区二区三区久久久| 尹人香蕉久久99天天拍| 亚洲国产婷婷香蕉久久久久久| 人妻少妇精品久久| 精品久久久久成人码免费动漫| 欧美麻豆久久久久久中文| 欧美久久综合九色综合| 久久精品aⅴ无码中文字字幕不卡 久久精品成人欧美大片 | 日韩欧美亚洲综合久久影院Ds| 久久久久久国产精品免费免费| 久久久久亚洲av成人无码电影| 国产—久久香蕉国产线看观看| 精品国产乱码久久久久久浪潮 | 思思久久99热只有频精品66| 久久久精品国产免大香伊| 一本色道久久88精品综合| 欧美一区二区三区久久综合 | 久久久这里有精品| 久久午夜羞羞影院免费观看| 香蕉久久夜色精品国产小说| 亚洲а∨天堂久久精品9966| 日韩精品久久无码中文字幕| 青青草原综合久久大伊人精品| 久久人人超碰精品CAOPOREN| 亚洲国产精品无码久久98| 久久最近最新中文字幕大全| 热RE99久久精品国产66热| 国产精品久久成人影院| 久久国内免费视频| 亚洲综合精品香蕉久久网97| 久久婷婷五月综合97色直播| 国产午夜福利精品久久| 九九精品久久久久久噜噜| 青草影院天堂男人久久| 亚洲精品无码久久久久sm| 日日狠狠久久偷偷色综合0| 国产91久久精品一区二区|