前言
在C語言中,對於一些常用或通用的代碼段的封裝可以有兩種方式:函數和宏定義。
這篇博客就來帶大家梳理一下對於這兩種方式我們在使用時應該如何抉擇,以及它們的區別和優缺點。
宏定義和函數的區別
- 從程序的執行來看:
函數調用需要開闢和釋放棧空間帶來開銷(存在函數調用壓棧和返回的額外開銷),不僅會降低代碼效率,而且代碼量也會大大增加。
宏定義只在編譯前進行,不分配空間,不佔運行時間。
總結:宏定義在代碼規模和速度方面都比函數更勝一籌
- 從參數的類型來看:
函數的參數必須聲明爲一種特定的數據類型,如果參數的類型不同,就需要使用不同的函數來解決。
宏定義的參數是無類型的,只要參數的操作是合法的,它可以用於任何參數類型。
總結:宏定義是類型無關的,較函數應用更爲廣泛
- 從參數的副作用來看:
宏定義中對宏參數缺少必要的類型檢查,宏的參數和返回值最好用()
括起來,否則可能導致返回值和預期的結果不符,宏的參數如果傳入自增自減型,則返回值也可能和預期不符。
函數則從根本上避免了這些問題的發生。
舉個栗子:
#define MAX(a,b) ((a)>(b)?(a):(b))
x = 5;
y = 8;
z = MAX(x++,y++);
printf("x=%d y=%d z=%d,x,y,z);
輸出結果:6 10 9
解析:
1.宏替換:MAX ( (x++) > (y++) ? (x++) : (y++) )
2.比大小:5 > 8 結果爲假(此時後置++操作x=6,y=9),返回y,此時後置++操作y=10
3.輸出:x=6,y=10,z爲返回值(也就是y++之前的值)z=9
- 從代碼的長度來看:
宏定義使用時,代碼的副本會插入程序中,除非宏非常短,否則使用宏會大幅度地增加程序的長度,並且宏是不方便調試且不能遞歸的。
函數代碼則只會出現在一個地方,以後每次調用這個函數時,調用的都是那個地方的同一份代碼
總結:宏定義的使用相較函數來說可能會大幅度增加程序的長度
從上面的四點分析:
函數和宏定義各有優缺點,這就要求我們根據具體情況具體分析,合理地對二者進行取捨
小結
綜上所述,如何取捨這二者,還需要根據具體情況具體分析,千萬不能夠武斷地做出判斷。一般來說,應該用宏去替換小的、可重複的代碼段,這樣可以使程序運行速度更快。當任務比較複雜,需要多行代碼才能實現時,或者要求程序越小越好時,就應該使用函數。