亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C/C++細(xì)數(shù)宏與函數(shù)有那些區(qū)別

 更新時(shí)間:2022年10月26日 15:26:55   作者:不一樣的煙火a  
在C程序中,可以用宏代碼提高執(zhí)行效率。宏代碼本身不是函數(shù),但使用起來象函數(shù)。預(yù)處理器用復(fù)制宏代碼的方式代替函數(shù)調(diào)用,省去了參數(shù)壓棧、生成匯編語言的CALL調(diào)用、返回參數(shù)、執(zhí)行return等過程,從而提高了速度

一、宏和函數(shù)的對(duì)比

1.宏的優(yōu)點(diǎn)

  • 宏通常被應(yīng)用于執(zhí)行簡單的運(yùn)算。
  • 比如在兩個(gè)數(shù)中找出較大的一個(gè)。
#define MAX(a, b) ((a)>(b)?(a):(b))

那為什么不用函數(shù)來完成這個(gè)任務(wù)?

原因有兩點(diǎn):

用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實(shí)際執(zhí)行這個(gè)小型計(jì)算工作所需要的時(shí)間更多。

所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。

舉例:

用宏實(shí)現(xiàn)兩個(gè)數(shù)中找出較大值。

#define MAX(x, y) ((x) > (y) ? (x) : (y))
int main()
{
	int a = 10;
	int b = 20;
	int c = MAX(a, b); // 宏
	return 0;
}

轉(zhuǎn)到反匯編,查看匯編代碼。

    int c = MAX(a, b); // 宏
00791783  mov         eax,dword ptr [a]  
00791786  cmp         eax,dword ptr [b]  
00791789  jle         __$EncStackInitStart+3Ah (0791796h)  
0079178B  mov         ecx,dword ptr [a]  
0079178E  mov         dword ptr [ebp-0E8h],ecx  
00791794  jmp         __$EncStackInitStart+43h (079179Fh)  
00791796  mov         edx,dword ptr [b]  
00791799  mov         dword ptr [ebp-0E8h],edx  
0079179F  mov         eax,dword ptr [ebp-0E8h]  
007917A5  mov         dword ptr [c],eax

用函數(shù)實(shí)現(xiàn)兩個(gè)數(shù)中找出較大值。

int Max(int x, int y)
{
	return ((x) > (y) ? (x) : (y));
}
int main()
{
	int a = 10;
	int b = 20;
	int c = Max(a, b); // 函數(shù)
	return 0;
}

調(diào)用函數(shù)的匯編代碼。

    int c = Max(a, b); // 函數(shù)
002C1793  mov         eax,dword ptr [b]  
002C1796  push        eax  
002C1797  mov         ecx,dword ptr [a]  
002C179A  push        ecx  
002C179B  call        _Max (02C139Dh)  // 調(diào)用Max函數(shù)
002C17A0  add         esp,8  
002C17A3  mov         dword ptr [c],eax  

計(jì)算的匯編代碼。

int Max(int x, int y)
{
002C1DF0  push        ebp  
002C1DF1  mov         ebp,esp  
002C1DF3  sub         esp,0C4h  
002C1DF9  push        ebx  
002C1DFA  push        esi  
002C1DFB  push        edi  
002C1DFC  lea         edi,[ebp-4]  
002C1DFF  mov         ecx,1  
002C1E04  mov         eax,0CCCCCCCCh  
002C1E09  rep stos    dword ptr es:[edi]  
002C1E0B  mov         ecx,offset _66EADA86_詳解預(yù)處理\test@c (02CC000h)  
002C1E10  call        @__CheckForDebuggerJustMyCode@4 (02C1307h)  
// 下面這些才是計(jì)算的代碼,上面這些代碼可以說還是在為調(diào)用函數(shù)做準(zhǔn)備
// 并且可以看出下面的匯編代碼和宏那里的匯編代碼是一樣的
    return ((x) > (y) ? (x) : (y));
002C1E15  mov         eax,dword ptr [x]  
002C1E18  cmp         eax,dword ptr [y]  
002C1E1B  jle         __$EncStackInitStart+2Ch (02C1E28h)  
002C1E1D  mov         ecx,dword ptr [x]  
002C1E20  mov         dword ptr [ebp-0C4h],ecx  
002C1E26  jmp         __$EncStackInitStart+35h (02C1E31h)  
002C1E28  mov         edx,dword ptr [y]  
002C1E2B  mov         dword ptr [ebp-0C4h],edx  
002C1E31  mov         eax,dword ptr [ebp-0C4h]  
}

函數(shù)返回的匯編代碼。

002C1E37  pop         edi  
002C1E38  pop         esi  
002C1E39  pop         ebx  
002C1E3A  add         esp,0C4h  
002C1E40  cmp         ebp,esp  
002C1E42  call        __RTC_CheckEsp (02C1230h)  
002C1E47  mov         esp,ebp  
002C1E49  pop         ebp  
002C1E4A  ret

總結(jié):

如果用函數(shù)的話,會(huì)經(jīng)過以下幾個(gè)步驟:

  • 函數(shù)調(diào)用。
  • 計(jì)算。
  • 函數(shù)返回。

根據(jù)上面的匯編代碼可以看出,函數(shù)調(diào)用和函數(shù)返回所用的匯編指令遠(yuǎn)多于計(jì)算所用的匯編指令,這就導(dǎo)致函數(shù)調(diào)用和返回所用的時(shí)間遠(yuǎn)多于計(jì)算所用的時(shí)間。而宏本質(zhì)是替換,不用進(jìn)行函數(shù)調(diào)用和返回,所以這就是宏在實(shí)現(xiàn)小型計(jì)算工作時(shí)比函數(shù)快的原因。

  • 更為重要的是函數(shù)的參數(shù)必須聲明為特定的類型。

所以函數(shù)只能在類型合適的表達(dá)式上使用。

而宏是類型無關(guān)的,宏可以適用于整形、長整型、浮點(diǎn)型等,可以用于 “>” 來比較的類型。

舉例:

下面為宏和函數(shù)實(shí)現(xiàn)的兩個(gè)數(shù)中找出較大值。

// 宏
#define MAX(x, y) ((x) > (y) ? (x) : (y))
// 函數(shù)
int Max(int x, int y)
{
	return ((x) > (y) ? (x) : (y));
}

可以看出,該函數(shù)只能對(duì)兩個(gè)int類型的數(shù)進(jìn)行比較,而宏卻可以對(duì)兩個(gè)任意類型的數(shù)進(jìn)行比較,這就使宏用起來更加的靈活。

2.宏的缺點(diǎn)

  1. 每次使用宏的時(shí)候,一份宏定義的代碼將插入到程序中。除非宏比較短,否則可能大幅度增加程序的長度。
  2. 宏是沒法調(diào)試的。
  3. 宏由于類型無關(guān),也就不夠嚴(yán)謹(jǐn)。
  4. 宏可能會(huì)帶來運(yùn)算符優(yōu)先級(jí)的問題,導(dǎo)致程容易出現(xiàn)錯(cuò)。

3.宏的獨(dú)特性

宏有時(shí)候可以做函數(shù)做不到的事情。

比如:宏的參數(shù)可以出現(xiàn)類型,但是函數(shù)做不到。

#define MALLOC(num, type) (type*)malloc(num * sizeof(type))
int main()
{
	// 使用
	int* p1 = MALLOC(10, int); // 替換后為 int* p1 = (int*)malloc(10 * sizeof(int));
	char* p2 = MALLOC(5, int); // 替換后為 int* p2 = (char*)malloc(5 * sizeof(char));
	return 0;
}

4.總結(jié)并整理宏和函數(shù)的區(qū)別

屬 性#define定義宏函數(shù)
代 碼 長 度每次使用時(shí),宏代碼都會(huì)被 插入到程序中。除了非常小的宏之外,程序的長度會(huì)大幅度增長函數(shù)代碼只出現(xiàn)于一個(gè)地方;每次使用這個(gè)函數(shù)時(shí),都調(diào)用那個(gè)地方的同一份代碼
執(zhí) 行 速 度更快存在函數(shù)的調(diào)用和返回的額外開銷,所以相對(duì)慢一些
操 作 符 優(yōu) 先 級(jí)宏參數(shù)的求值是在所有周圍表達(dá)式的上下文環(huán)境里,除非加上括號(hào),否則鄰近操作符的優(yōu)先級(jí)可能會(huì)產(chǎn)生不可預(yù)料的后果,所以建議宏在書寫的時(shí)候多些括號(hào)。函數(shù)參數(shù)只在函數(shù)調(diào)用的時(shí)候求值一次,它的結(jié)果值傳遞給函數(shù)。表達(dá)式的求值結(jié)果更容易預(yù) 測(cè)。
帶 有 副 作 用 的 參 數(shù)參數(shù)可能被替換到宏體中的多個(gè)位置,所以帶有副作用的參數(shù)求值可能會(huì)產(chǎn)生不可預(yù)料的結(jié)果。函數(shù)參數(shù)只在傳參的時(shí)候求值一 次,結(jié)果更容易控制。
參 數(shù) 類 型宏的參數(shù)與類型無關(guān),只要對(duì)參數(shù)的操作是合法的, 它就可以使用于任何參數(shù)類型。函數(shù)的參數(shù)是與類型有關(guān)的,如果參數(shù)的類型不同,就需要不同的函數(shù),即使他們執(zhí)行的任務(wù)是 不同的。
調(diào) 試宏是不方便調(diào)試的函數(shù)是可以逐語句調(diào)試的
遞 歸宏是不能遞歸的函數(shù)是可以遞歸的

5.有沒有宏和函數(shù)的結(jié)合體

答案是當(dāng)然有。

在C99和C++里面都有一個(gè)東西叫做內(nèi)聯(lián)函數(shù)(inline)

內(nèi)聯(lián)函數(shù)既有函數(shù)的優(yōu)點(diǎn)又有宏的優(yōu)點(diǎn):

  • 宏的優(yōu)點(diǎn):內(nèi)聯(lián)函數(shù)沒有函數(shù)的調(diào)用和返回。
  • 函數(shù)的優(yōu)點(diǎn): 內(nèi)聯(lián)函數(shù)本身是個(gè)函數(shù),它沒有參數(shù)優(yōu)先級(jí)、副作用等宏的缺點(diǎn)。

提示:由于本篇文章主要是講宏和函數(shù)的區(qū)別,內(nèi)聯(lián)函數(shù)就不多講,這里只做了解,后面我會(huì)單獨(dú)寫一篇文章來講解內(nèi)聯(lián)函數(shù)的。

二、宏和函數(shù)的命名約定

一般來講函數(shù)的宏的使用語法很相似。所以語言本身沒法幫我們區(qū)分二者。

那么我們平時(shí)就應(yīng)該有一個(gè)良好的書寫習(xí)慣:

把宏名全部大寫

函數(shù)名不要全部大寫

這里可以參考《高質(zhì)量C/C++編程指南》這本書,有興趣的小伙伴可以去看看。

到此這篇關(guān)于C/C++細(xì)數(shù)宏與函數(shù)有那些區(qū)別的文章就介紹到這了,更多相關(guān)C/C++宏與函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言簡析指針用途

    C語言簡析指針用途

    C語言這門課程在計(jì)算機(jī)的基礎(chǔ)教學(xué)中一直占有比較重要的地位,然而要想突破C語言的學(xué)習(xí),對(duì)指針的掌握是非常重要的,本文將具體針對(duì)指針的基礎(chǔ)做詳盡的介紹
    2022-07-07
  • C語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)串(堆分配存儲(chǔ)表示法)實(shí)例詳解

    C語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)串(堆分配存儲(chǔ)表示法)實(shí)例詳解

    這篇文章主要介紹了C語言實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)串(堆分配存儲(chǔ)表示法)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • C++中靜態(tài)庫與動(dòng)態(tài)庫的使用示例

    C++中靜態(tài)庫與動(dòng)態(tài)庫的使用示例

    在C/C++中使用庫的技術(shù),庫主要分為兩種類型:靜態(tài)庫和動(dòng)態(tài)庫,本文主要介紹了C++中靜態(tài)庫與動(dòng)態(tài)庫的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • C++采用openfilename打開文件對(duì)話框用法實(shí)例

    C++采用openfilename打開文件對(duì)話框用法實(shí)例

    這篇文章主要介紹了C++采用openfilename打開文件對(duì)話框用法實(shí)例,是C++文件操作中非常實(shí)用的技巧,需要的朋友可以參考下
    2014-10-10
  • c語言conio.h基本知識(shí)點(diǎn)總結(jié)

    c語言conio.h基本知識(shí)點(diǎn)總結(jié)

    在本篇文章里小編給大家分享的是關(guān)于c語言conio.h是什么意思的相關(guān)知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)參考下。
    2020-02-02
  • OpenCV實(shí)現(xiàn)透視變換矯正

    OpenCV實(shí)現(xiàn)透視變換矯正

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)透視變換矯正,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • vc中SendMessage自定義消息函數(shù)用法實(shí)例

    vc中SendMessage自定義消息函數(shù)用法實(shí)例

    這篇文章主要介紹了vc中SendMessage自定義消息函數(shù)用法,以實(shí)例實(shí)行詳細(xì)講述了SendMessage的定義、原理與用法,具有一定的實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • Qt使用流處理XML文件的示例代碼

    Qt使用流處理XML文件的示例代碼

    XML(eXtensible?Markup?Language)是一種通用的文本格式,被廣泛運(yùn)用于數(shù)據(jù)交換和數(shù)據(jù)存儲(chǔ)。本文主要來和大家聊聊如何使用?Qt?處理?XML?格式的文檔,需要的可以參考一下
    2023-02-02
  • C++詳細(xì)分析lambda表達(dá)式的本質(zhì)

    C++詳細(xì)分析lambda表達(dá)式的本質(zhì)

    Lambda表達(dá)式是現(xiàn)代C++在C ++ 11和更高版本中的一個(gè)新的語法糖 ,在C++11、C++14、C++17和C++20中Lambda表達(dá)的內(nèi)容還在不斷更新。 lambda表達(dá)式(也稱為lambda函數(shù))是在調(diào)用或作為函數(shù)參數(shù)傳遞的位置處定義匿名函數(shù)對(duì)象的便捷方法
    2022-06-06
  • C++實(shí)現(xiàn)推箱子游戲

    C++實(shí)現(xiàn)推箱子游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)推箱子游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10

最新評(píng)論