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

              C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              117 Posts :: 2 Stories :: 61 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(8)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

                  函數(shù)是C++語(yǔ)言的基本功能單位,一般來(lái)說(shuō),函數(shù)的功能單一,函數(shù)代碼不可過(guò)長(zhǎng)。函數(shù)接口設(shè)計(jì)清晰明了,返回值和錯(cuò)誤代碼的返回分開(kāi)。除了普通的函數(shù)之外,還有內(nèi)聯(lián)函數(shù)、回調(diào)函數(shù)等。在不同語(yǔ)言之間的調(diào)用函數(shù),提供了不同的調(diào)用規(guī)范。所謂預(yù)處理是指在進(jìn)行編譯的第一遍掃描(詞法掃描和語(yǔ)法分析)之前所做的工作。預(yù)處理是C++語(yǔ)言的一個(gè)重要功能,它由預(yù)處理程序負(fù)責(zé)完成。當(dāng)對(duì)一個(gè)源文件進(jìn)行編譯時(shí),系統(tǒng)將自動(dòng)引用預(yù)處理程序?qū)υ闯绦蛑械念A(yù)處理部分進(jìn)行處理,處理完畢自動(dòng)進(jìn)入對(duì)源程序的編譯。C++語(yǔ)言提供了多種預(yù)處理功能,如宏定義、文件包含、條件編譯等。合理地使用預(yù)處理功能編寫(xiě)的程序便于閱讀、修改、移植和調(diào)試,也有利于模塊化程序設(shè)計(jì)。

            1、 在C++中調(diào)用C編譯器的函數(shù)

                  1.1   C++中調(diào)用C編譯器的函數(shù)的原理

                  C++語(yǔ)言,曾經(jīng)有一叫法是帶類的C語(yǔ)言,那也就是說(shuō)它的前身是C語(yǔ)言,所以說(shuō),用C寫(xiě)的函數(shù),基本上是可以在C++中調(diào)用的。比如說(shuō),C語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的函數(shù),在C++中是可以調(diào)用的。但是    C++畢竟跟C不同,那怎樣才能順利地把C函數(shù)應(yīng)用到C++中呢?下面來(lái)討論這個(gè)問(wèn)題。

                  C++語(yǔ)言支持函數(shù)重載,C語(yǔ)言不支持函數(shù)重載。函數(shù)被C++編譯后在庫(kù)中的名字與C語(yǔ)言的不同。

                  1.2   實(shí)例代碼

                  假設(shè)某個(gè)C函數(shù)的聲明如下:

                void foo(int x, int y);

                  該函數(shù)被C編譯器編譯后在庫(kù)中的名字為_foo,而C++編譯器則會(huì)產(chǎn)生像_foo_int_int之類的名字用來(lái)支持函數(shù)重載和類型安全連接。由于編譯后的名字不同,C++程序不能直接調(diào)用C函數(shù)。C++提供了一個(gè)C連接交換指定符號(hào)extern”C”來(lái)解決這個(gè)問(wèn)題。例如

            extern “C”
            {
            void foo(int x, int y);
            //其他函數(shù)
            }

            或者寫(xiě)成
            extern “C”
            {
            #include “myheader.h”
            //其他C頭文件
            }

                  這就告訴C++編譯器,函數(shù)foo是個(gè)C連接,應(yīng)該到庫(kù)中找名字_foo而不是找_foo_int_intC++編譯器開(kāi)發(fā)商已經(jīng)對(duì)C標(biāo)準(zhǔn)庫(kù)的頭文件做了extern”C”處理,所以可以用#include直接引用這些頭文件。

                  如果調(diào)用自己寫(xiě)的C函數(shù),可以把C函數(shù)集合成一個(gè)庫(kù),然后把其相應(yīng)的頭文件用extern”C”處理,用#include直接引用這些頭文件即可。

            2、 內(nèi)聯(lián)函數(shù)和宏的比較

                  2.1 內(nèi)聯(lián)函數(shù)的概念

                  在C++中,可以將函數(shù)指定為內(nèi)聯(lián)(inline)的,這樣,編譯器會(huì)在調(diào)用該函數(shù)的每個(gè)地方產(chǎn)生該函數(shù)的一個(gè)副本。使用內(nèi)聯(lián)函數(shù)可以減少函數(shù)調(diào)用帶來(lái)的開(kāi)銷(xiāo),不過(guò)應(yīng)該在函數(shù)很簡(jiǎn)單而且在調(diào)用次數(shù)相對(duì)較少的情況下,才將其指定為內(nèi)聯(lián)的。

                  內(nèi)聯(lián)函數(shù)的基本思想在于將每個(gè)函數(shù)調(diào)用以它的代碼體來(lái)替換。用不著統(tǒng)計(jì)專家出面就可以看出,這種做法很可能會(huì)增加整個(gè)目標(biāo)代碼的體積。在一臺(tái)內(nèi)存有限的計(jì)算機(jī)里,過(guò)分地使用內(nèi)聯(lián)所產(chǎn)生的程序會(huì)因?yàn)橛刑蟮捏w積而導(dǎo)致可用空間不夠。即使可以使用虛擬內(nèi)存,內(nèi)聯(lián)造成的代碼膨脹也可能會(huì)導(dǎo)致不合理的頁(yè)面調(diào)度行為(系統(tǒng)顛簸),這將使你的程序運(yùn)行慢得象在爬。(當(dāng)然,它也為磁盤(pán)控制器提供了一個(gè)極好的鍛煉方式:)
                  過(guò)多的內(nèi)聯(lián)還會(huì)降低指令高速緩存的命中率,從而使取指令的速度降低,因?yàn)閺闹鞔嫒≈噶町?dāng)然比從緩存要慢。另一方面,如果內(nèi)聯(lián)函數(shù)體非常短,編譯器為這個(gè)函數(shù)體生成的代碼就會(huì)真的比為函數(shù)調(diào)用生成的代碼要小許多。如果是這種情況,內(nèi)聯(lián)這個(gè)函數(shù)將會(huì)確實(shí)帶來(lái)更小的目標(biāo)代碼和更高的緩存命中率!要牢記在心的一條是,
            inline指令就象register,它只是對(duì)編譯器的一種提示,而不是命令。也就是說(shuō),只要編譯器愿意,它就可以隨意地忽略掉你的指令,事實(shí)上編譯器常常會(huì)這么做。例如,大多數(shù)編譯器拒絕內(nèi)聯(lián)"復(fù)雜"的函數(shù)。
                  摘自
            Effective   C++2e,建議看一下《深度探索C++對(duì)象模型〉

                  2.2 內(nèi)聯(lián)函數(shù)和宏的比較

                  兩者相同之處是,在其出現(xiàn)的地方將代碼替換。但是區(qū)別很大。

                  對(duì)于宏來(lái)說(shuō),C++中不贊成使用,除非程序中一定要用宏時(shí)。宏只是在編譯前(編譯處理階段)將程序中有關(guān)字符串替換成宏體,也不進(jìn)行參數(shù)類型等的檢查,容易出錯(cuò)

                  對(duì)于內(nèi)聯(lián)函數(shù)來(lái)說(shuō),其不是通過(guò)函數(shù)調(diào)用實(shí)現(xiàn)的,是在調(diào)用該函數(shù)的程序處將它展開(kāi),這是在程序的編譯期間完成的,期間進(jìn)行諸如類型檢測(cè)等過(guò)程,減少了錯(cuò)誤的發(fā)生

                  2.3 應(yīng)用規(guī)則

                  ·宏盡量少用,或不用。

                  ·內(nèi)聯(lián)函數(shù)不宜過(guò)大,過(guò)復(fù)雜

                  ·內(nèi)聯(lián)函數(shù)是建議性而非指令性的,過(guò)大或過(guò)復(fù)雜,會(huì)被系統(tǒng)忽略,而當(dāng)成一般函數(shù)用了。

                  ·內(nèi)聯(lián)函數(shù)一般不要超過(guò)5行,而且經(jīng)常要用時(shí)才聲明稱內(nèi)聯(lián)函數(shù)

            3、 #include<filename.h>和#include “filename.h”的區(qū)別

                  3.1 包含文件

                  #inculde預(yù)處理指令的作用是在指令處展開(kāi)被包含的文件,包含可以是多重的,也就是說(shuō),一個(gè)被包含的文件中海可以包含其他的文件。

                  3.2 包含頭文件有兩種格式

                  一種就是#include<文件名>,另一種是#include ”文件名

                  用尖括號(hào)包括頭文件,這是C++的標(biāo)準(zhǔn)方式,一般這些頭文件都存放于C++系統(tǒng)目錄中的include子目錄下,C++預(yù)處理碰到這種情況后,就到include目錄下搜索給出的文件。

                  用引號(hào)包括頭文件,適用于用戶自己寫(xiě)的頭文件中,預(yù)處理碰到這種格式,就先在當(dāng)前目錄下進(jìn)行搜索,如果找不到,再到系統(tǒng)目錄下進(jìn)行搜索。

            4、 回調(diào)函數(shù)的概念與操作技巧

                  4.1 回調(diào)函數(shù)的概念

                  回調(diào)函數(shù)就是在調(diào)用某個(gè)函數(shù)(通常是API函數(shù))時(shí),將用戶自己的一個(gè)函數(shù)(這個(gè)函數(shù)為回調(diào)函數(shù))的地址作為參數(shù)傳遞給那個(gè)函數(shù)。而那個(gè)函數(shù)在需要的時(shí)候,利用傳遞的地址調(diào)用用戶自己定義的函數(shù),這時(shí)在回調(diào)函數(shù)中處理消息或完成一定得操作。

                  4.2 回調(diào)函數(shù)的實(shí)現(xiàn)

                  回調(diào)函數(shù)調(diào)用是利用其函數(shù)地址調(diào)用函數(shù)的,實(shí)現(xiàn)函數(shù)的功能。要實(shí)現(xiàn)一個(gè)回調(diào)函數(shù),首先要實(shí)現(xiàn)一個(gè)函數(shù)指針,讓這個(gè)指針指向功能函數(shù),然后利用函數(shù)指針,隱式調(diào)用函數(shù)。

            #include<iostream.h>
            //聲明功能函數(shù):
            void fun()
            {
              cout
            <<"this is a callback test"<<endl;
            }

            //聲明指針函數(shù):
            void (*p) (); //指針p指向一個(gè)參數(shù)為空,返回值為void的功能函數(shù)
            //聲明調(diào)用函數(shù)caller,函數(shù)的參數(shù)是返回值為void,參數(shù)為空的函數(shù)指針:
            void caller(void (*ptr)())
            {
              ptr();
            }

            //主函數(shù)實(shí)現(xiàn)
            int main()
            {
              p
            =fun;
              caller(p);
              
            return 0;
            }

                   4.3 回調(diào)函數(shù)的應(yīng)用

                   回調(diào)函數(shù)在Windows系統(tǒng)編程中用的較多,比如MouseProGetMsgProcEnumWindows、DrawState

            例如API函數(shù)

            EnumFonts(HDC hdc,
            LPCTSTR lpFaceName,
            FONTENUMPROC,
            PARAM lParam
            );

            在使用時(shí)需要定義一個(gè)回調(diào)函數(shù):

            Int CALLBACK EnumFontsProc(
            CONST LOCFONT 
            *lplf,
            CONST TEXTMETRIC 
            *lptm,
            DWORD dwTtype,
            LPARAM lpDate
            );

                  然后寫(xiě)EnumFonts(hdc,null,EnumFontsProc)即可。在使用計(jì)時(shí)器時(shí),把計(jì)時(shí)器消息發(fā)送給程序的另一個(gè)函數(shù),接收這些計(jì)時(shí)器消息的函數(shù)被稱為“回調(diào)”函數(shù),這是一個(gè)在程序中,但是由Windows調(diào)用的函數(shù)。程序的窗口過(guò)程實(shí)際上也是一類回調(diào)函數(shù),當(dāng)注冊(cè)窗口類時(shí),要將函數(shù)的地址告訴Windows,當(dāng)發(fā)送消息給程序時(shí),Windows調(diào)用此函數(shù)。

            5、 函數(shù)的調(diào)用規(guī)范

                  當(dāng)程序被執(zhí)行時(shí),CPU無(wú)法知道函數(shù)的調(diào)用需要多少個(gè)、什么樣的參數(shù),那么也就是說(shuō)計(jì)算機(jī)無(wú)法知道如何給這個(gè)函數(shù)傳遞參數(shù)。函數(shù)的調(diào)用時(shí)由調(diào)用者和被調(diào)用者協(xié)作完成的。計(jì)算機(jī)為此專門(mén)提供了棧的數(shù)據(jù)結(jié)構(gòu),支持參數(shù)的傳遞。函數(shù)調(diào)用時(shí),參數(shù)執(zhí)行壓棧操作,然后開(kāi)始調(diào)用函數(shù),函數(shù)被調(diào)用以后,參數(shù)值出棧,參與函數(shù)功能實(shí)現(xiàn)后,進(jìn)行棧的清理工作。在參數(shù)傳遞中,當(dāng)參數(shù)多于一個(gè)時(shí),按照什么順序壓棧,函數(shù)調(diào)用后,由誰(shuí)把堆?;貜?fù)。

                  在高級(jí)語(yǔ)言中,通過(guò)函數(shù)調(diào)用規(guī)范(Calling Conventions)來(lái)說(shuō)明這三個(gè)問(wèn)題。常見(jiàn)的調(diào)用規(guī)范有:stdcall、cdecl。

                  1.    stdcall調(diào)用規(guī)范

                  這是Win API函數(shù)使用的調(diào)用規(guī)范。參數(shù)從右向左一次傳遞并壓入堆棧,由被調(diào)用函數(shù)負(fù)責(zé)堆棧的清退。該規(guī)范生產(chǎn)代碼比_cdecl更小,但當(dāng)函數(shù)有可變個(gè)數(shù)的參數(shù)時(shí)會(huì)轉(zhuǎn)為_cdecl規(guī)范。在Windows中,宏WINAPI、CALLBACK都定義為_stdcall。

                  stdcall調(diào)用規(guī)范聲明的語(yǔ)法為:

            int _stdcall function(int a, int b)

                  利用stdcall調(diào)用,參數(shù)從右向左壓入堆棧,函數(shù)自身修改堆棧,調(diào)用時(shí)函數(shù)名自動(dòng)加前導(dǎo)的下劃線,后面緊跟一個(gè)@符號(hào),其后緊跟著參數(shù)的尺寸。以上述這個(gè)函數(shù)為例,參數(shù)b首先被壓棧,然后是參數(shù)a,函數(shù)調(diào)用function(1,2),而在編譯時(shí),這個(gè)函數(shù)的名字被翻譯成_function@8

                  2.   cdecl調(diào)用規(guī)范

                  cdecl調(diào)用約定又被稱為C調(diào)用約定,是C語(yǔ)言默認(rèn)的調(diào)用約定,它的定義語(yǔ)法是:

            int function(int a, int b) //不加修飾就是C調(diào)用約定

            int _cdecl function(int a, int b) //明確指出C調(diào)用約定

                  cdecl調(diào)用約定的參數(shù)壓棧順序是和stdcall一樣的,參數(shù)首先由右向左壓入堆棧。所不同的是,函數(shù)本身不清理堆棧,調(diào)用者負(fù)責(zé)清理堆棧。由于這種變化,C調(diào)用約定允許函數(shù)的參數(shù)個(gè)數(shù)是不固定的,這也是C語(yǔ)言的一大特色。對(duì)于前面的function函數(shù),該修飾自動(dòng)在函數(shù)名前加前導(dǎo)的下劃線,因此函數(shù)名在符號(hào)表中被記錄為_function

                  3.   函數(shù)調(diào)用約定導(dǎo)致的常見(jiàn)問(wèn)題

                  如果定義的約定和使用的約定不一致,將導(dǎo)致堆棧被破壞,導(dǎo)致嚴(yán)重問(wèn)題,下面是兩種常見(jiàn)的問(wèn)題。

                  ·函數(shù)原型聲明和函數(shù)體定義不一致

                  ·DLL導(dǎo)入函數(shù)時(shí)聲明了不同的函數(shù)約定

            如果還想獲得更多關(guān)于《Visual C++代碼參考與技巧大全》的內(nèi)容,可點(diǎn)擊下面網(wǎng)址,

            http://www.shnenglu.com/kangnixi/archive/2010/01/13/105591.html

            亚洲愉拍99热成人精品热久久 | 91久久国产视频| 国产精品久久久久久久久久免费| 国产精品久久久久久五月尺| 久久91精品综合国产首页| 国产精品18久久久久久vr| 四虎亚洲国产成人久久精品| 国产精品久久久天天影视香蕉| av无码久久久久不卡免费网站| 中文字幕热久久久久久久| 人人妻久久人人澡人人爽人人精品 | 夜夜亚洲天天久久| 国内精品久久久久| 久久久精品午夜免费不卡| 国产99精品久久| 国产精品99久久久久久猫咪| 国产精品成人99久久久久91gav| 91秦先生久久久久久久| 99久久精品这里只有精品| 精品久久久久中文字| 久久久91人妻无码精品蜜桃HD| 久久久久久国产精品美女 | 国产三级精品久久| 久久人人爽人爽人人爽av| 久久亚洲av无码精品浪潮| 97视频久久久| 久久亚洲中文字幕精品有坂深雪 | 人人狠狠综合久久亚洲88| 国产高潮国产高潮久久久91 | 久久国产精品久久国产精品| 国产综合精品久久亚洲| 亚洲精品无码久久毛片 | 一本一本久久A久久综合精品| 久久天天躁狠狠躁夜夜avapp| 9久久9久久精品| 久久久网中文字幕| 色8久久人人97超碰香蕉987| 亚洲一区中文字幕久久| 久久久亚洲欧洲日产国码是AV| 精品久久久久久无码专区不卡| 国产亚洲精午夜久久久久久|