函數式宏界說與通俗函數的差別。本站提示廣大學習愛好者:(函數式宏界說與通俗函數的差別)文章只能為提供參考,不一定能成為您想要的結果。以下是函數式宏界說與通俗函數的差別正文
在C及C++說話中許可用一個標識符來表現一個字符串,稱為宏,該字符串可所以常數、表達式、格局串等。在編譯預處置時,對法式中一切湧現的“宏名”,都用宏界說中的字符串去代換,這稱為“宏代換”或“宏睜開”。宏界說是由源法式中的宏界說敕令完成的。宏代換是由預處置法式主動完成的。若字符串是表達式,我們稱之為函數式宏界說,那函數式宏界說與通俗函數有甚麼差別呢?
我們以上面兩行代碼為例,睜開描寫:
函數式宏界說:#define MAX(a,b) ((a)>(b)?(a):(b))
通俗函數 :MAX(a,b) { return a>b?a:b;}
(1)函數式宏界說的參數沒有類型,預處置器只擔任做情勢上的調換,而不做參數類型檢討,所以傳參時要非分特別當心。
(2)挪用真正函數的代碼和挪用函數式宏界說的代碼編譯生成的指令分歧。
假如MAX是個通俗函數,那末它的函數體return a > b ? a : b; 要編譯生成指令,代碼中湧現的每次挪用也要編譯生成傳參指令和call指令。而假如MAX是個函數式宏界說,這個宏界說自己倒不用編譯生成指令,然則代碼中湧現的每次挪用編譯生成的指令都相當於一個函數體,而不是簡略的幾條傳參指令和call指令。所以,應用函數式宏界說編譯生成的目的文件會比擬年夜。
(3)函數式宏界說要留意格局,特別是括號。
假如下面的函數式宏界說寫成 #define MAX(a, b) (a>b?a:b),省去內層括號,則宏睜開就成了k = (i&0x0f>j&0x0f?i&0x0f:j&0x0f),運算的優先級就錯了。異樣事理,這個宏界說的外層括號也是不克不及省的。若函數中是宏調換為 ++MAX(a,b),則宏睜開就成了 ++(a)>(b)?(a):(b),運算優先級也是錯了。
(4)若函數參數為表達式,則通俗函數的挪用與函數式宏界說的調換進程是紛歧樣的。
通俗函數挪用時先務實參表達式的值再傳給形參,假如實參表達式有Side Effect,那末這些SideEffect只產生一次。例如MAX(++a, ++b),假如MAX是通俗函數,a和b只增長一次。但假如MAX函數式宏界說,則要睜開成k = ((++a)>(++b)?(++a):(++b)),a和b就紛歧定是增長一次照樣兩次了。所以若參數是表達式,調換函數式宏界說時必定要細心看好。
(5)函數式宏界說常常會招致較低的代碼履行效力。
看上面一段代碼:
int a[]={9,3,5,2,1,0,8,7,6,4};
int max(n)
{
return n==0?a[0]:MAX(a[n],max(n-1));
}
int main()
{
max(9);
return 0;
}
若是通俗函數,則經由過程遞歸,可取的最年夜值,時光龐雜度為O(n)。但如果是函數式宏界說,則宏睜開為( a[n]>max(n-1)?a[n]:max(n-1) ),個中max(n-1)被挪用了兩遍,如許依此遞歸下去,時光龐雜度會很高。
雖然函數式宏界說和通俗函數比擬有許多缺陷,但只需當心應用照樣會明顯進步代碼的履行效力,究竟省去了分派和釋放棧幀、傳參、傳前往值等一系列任務,是以那些冗長而且被頻仍挪用的函數常常用函數式宏界說來取代完成。