[轉]宏定義和函數調用的區別


含參數的宏與函數的區別

?         宏替換不占運行時間,只占編譯時間;而函數調用則占運行時間(分配單元、保留現場、值傳遞、返回),所以每次執行都要載入所以執行起來比較慢一些。。

?         定義宏的時候不要在宏及其參數之間鍵入空格,因為宏替換的時候會把你不經意打的空格當作宏的一部分進去。

?         在宏定義中把每個參數都用括號括起來,同時把整個結果也用括號(對於單個表達式的宏,可以使用小括號(),對於宏定義的復合語句可以使用{},Linux內核中有一個比較好的宏定義,do {…}while(0))括起來,以防止當宏用於一個更大的表達式時可能出現的問題。

?         使用宏次數多時,宏展開后源程序長,因為每展開一次都使程序增長,但是執行起來比較快一點(這也不是絕對的,當有很多宏展開,目標文件很大,執行的時候運行時系統換頁頻繁,效率就會低下)。而函數調用不使源程序變長。

?         函數調用時,先求出實參表達式的值,然后帶入形參。而使用帶參的宏只是進行簡單的字符替換。

?         函數調用是在程序運行時處理的,分配臨時的內存單元;而宏展開則是在編譯時進行的,在展開時並不分配內存單元,不進行值的傳遞處理,也沒有“返回值”的概念。

?         對函數中的實參和形參都要定義類型,二者的類型要求一致,如不一致,應進行類型轉換;而宏不存在類型問題,宏名無類型,它的參數也無類型,只是一個符號代表,展開時帶入指定的字符即可。宏定義時,字符串可以是任何類型的數據。

?         調用函數只可得到一個返回值,且有返回類型,而宏沒有返回值和返回類型,但是用宏可以設法得到幾個結果。

?         函數體內有Bug,可以在函數體內打斷點調試。如果宏體內有Bug,那么在執行的時候是不能對宏調試的,即不能深入到宏內部。

?         C++中宏不能訪問對象的私有成員,但是成員函數就可以。

?         宏的定義很容易產生二義性,如:定義#define S(a) (a)*(a),代碼S(a++),宏展開變成(a++)*(a++)這個大家都知道,在不同編譯環境下會有不同結果。

內聯函數和宏的區別(內聯函數的優點)

內聯函數和宏的區別在於,宏是由預處理器對宏進行替代,而內聯函數是通過編譯器控制來實現的。而且內聯函數是真正的函數,只是在需要用到的時候,內聯函數像宏一樣的展開,所以取消了函數的參數壓棧,減少了調用的開銷。你可以象調用函數一樣來調用內聯函數,而不必擔心會產生於處理宏的一些問題。

我們可以用Inline來定義內聯函數,不過,任何在類的說明部分定義的函數都會被自動的認為是內聯函數。(當然內聯函數的識別對編譯器來說是一個復雜的工作,后繼可能有專門的論述)

當然,內聯函數也有一定的局限性。就是函數中的執行代碼不能太多了,如果,內聯函數的函數體過大,一般的編譯器會放棄內聯方式,而采用普通的方式調用函數。這樣,內聯函數就和普通函數執行效率一樣了。

內聯函數通過避免被調用的開銷來提高執行效率,尤其是它能夠通過調用(“過程化集成”)被編譯器優化。

如何選擇使用宏還是函數:以下情況可以選擇宏,其他情況最好選用函數

2        一般來說,用宏來代表簡短的表達式比較合適。

2        在考慮效率的時候,可以考慮使用宏,或者內聯函數。

2        在頭文件保護(防止重復包含編譯),條件編譯中的#ifdef,#if defined以及assert的實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM