巨集和函式的區別

2021-09-23 06:08:50 字數 2399 閱讀 2554

1、執行速度(效率)

#define 巨集 的執行速度快,而函式由於存在函式呼叫以及函式返回時的額外開銷,因此函式的執行速度慢一些。通俗點來講,就是#define 巨集在程式執行過程中,只執行邏輯部分。而函式需要做一些準備工作,比如呼叫函式前要先在棧中預開闢一片空間,呼叫函式時執行邏輯部分,並且會儲存呼叫函式的位址,函式呼叫結束後根據儲存的位址返回到之前函式呼叫的地方,顯然,#define 巨集的執行速度快一些。
2、除錯

#define 巨集 不便於除錯,編譯報錯時,往往編譯器報錯的地方並不是真正發生錯誤的地方,而函式除錯是比較方便的。這是因為#define 巨集是在編譯時的預處理階段就被編譯器處理了,只完成一些替換操作,而函式是在程式執行過程中被處理的。

3、**長度

在編譯的預處理階段,#define 巨集 會被替換掉,假如巨集定義特別多,那麼會使得**長度大幅度增加,而函式只有在呼叫時才會使用定義函式的**,並且函式呼叫結束後會釋放掉呼叫期間開闢的空間,這並不會影響**的長度。

4、引數型別

#define 巨集 與型別無關,也就是說,巨集可以用於任何操作合法的引數型別,而函式的引數是與型別有關的,如果引數的型別不同,就需要不同的函式,並且,函式傳參是不可以傳入資料型別的。

# include # define malloc(num, type) (type *)malloc(num * sizeof(type))  //巨集在傳參時是可以傳入型別的

int max = 0;

max = max(x, int, y, int); //error 函式在傳參時是不可以傳入資料型別的

5、操作符的優先順序

#define 巨集 引數的求值需要給引數加上相應的括號,否則鄰近操作符可能會影響所求值的結果,這是因為巨集只是做了簡單的替換操作。而函式的引數只在函式呼叫時求值一次,並將結果傳遞給函式即可。

# include # define square(x) x*x

int main(void)

我們期待的結果是44=16,而執行上述程式的結果卻是7,這是因為巨集只是做了簡單的替換,因此可以得到替換後的結果為:3+13+1=7。

假如想要得到結果16,我們可以通過加上括號的方式來解決:

# include # define square(x) ((x)*(x))

int main(void)

函式在呼叫時先將引數計算一次,然後將結果傳給函式。

# include int square(int x)

int main(void)

6、引數求值

#define 巨集 引數每次用於巨集定義時,都將重新求值,這樣帶有***的巨集引數就可能會使得計算結果出錯,而函式的引數只在函式呼叫時求值一次,之後的多次函式呼叫中都不會改變其值。

先來看下這段**:

# include # define max(x, y) ((x) > (y) ? (x) : (y))

int main(void)

以上就是巨集引數對巨集產生的***,首先展開巨集引數可以得到(x++)>(y++)?(x++):(y++),由於是後置++,因此先給x,y賦值,此時x=2,y=5,顯然2<5,將執行:後面的語句,此時x自增1,變成3,y自增1變成6,而?後面的語句不被執行,x最終的值就是3。在執行:後面的語句時,y為6,同樣的後置++,把6賦給該語句,此時ret的值就是6,最後y自增1得到7。

再來看看下面這段**:

# include int max(int x, int y)

int main(void)

呼叫函式max時,將引數x++,y++傳進去,由於後置++,因此先賦值後自增,傳給函式的值是x=2,y=5,經過比較後返回5給函式,函式呼叫結束後x,y分別自增1,x變為3,y變為6。

因此,我們應該盡量避免使用帶有***的巨集引數。

綜上所述,我們發現,巨集和函式相比,有優勢,也有劣勢。那麼是否有一種方法既可以替代巨集,又可以替代函式呢?答案是肯定的,那就是內聯函式(ps:inline)。它接收資料型別的檢查,並且可以像巨集那樣展開,還可以像函式一樣被除錯。

總結下幾種替換巨集的方式:

1.c++中用const來代替巨集常量;

2.使用inline來代替巨集函式(包含型別檢測);

3.使用typedef來代替define定義的型別;

4.使用enum來代替定義多個巨集常量,並且enum定義的常量可讀性更高。

下面是對巨集和

函式區別的總結

巨集和函式的區別

巨集定義又稱巨集代替,巨集替換,其宣告方式為 define name parameter list stuff。其中,parameter list 引數列表 是乙個有逗號分隔的符號列表,它們可能出現在stuff中。必須注意的是,引數列表的左括號必須與name緊密相連,如果兩者之間有任何空格存在,則引...

巨集和函式的區別

巨集非常頻繁的運用於執行簡單的計算。那麼,為什麼不用函式呢?1.巨集在使用時比函式在程式的規模和速度更勝一籌。2.函式的引數必須申明為乙個特定的型別,於是它只能在型別合適的表示式使用。而巨集為無型別替換。而有些情況只能用巨集,就是按型別申請空間時。如 define malloc n,type typ...

巨集和函式的區別

語言學習過程中,我們總會使用函式和巨集,以提高 可讀性,而要想更好的使用它們,就得了解清楚巨集和函式的區別,下面我們就來細數一下巨集和函式到底有什麼不同 1.長度不同。當執行程式時,在預處理階段,巨集 被插入到程式中,使程式的長度大幅度增長,下面這個例子是在只有乙個巨集的情況下 include de...