巨集和函式的區別

巨集的定義:#define 機制包括了一個規定,允許把引數替換到文字中,這種實現通常稱為巨集(macro),或者定義巨集(define macro)。
函式:它負責完成某項特定任務,而且相較於其他程式碼,具備相對的獨立性。每次使用時只需要呼叫即可
——————————————————————————————————————————————————————————————————————————————
函式和巨集的區別主要從下面幾個方面來討論:
1.程式碼長度:
巨集:每次使用時程式碼巨集都會被插入到程式中,除了非常小的巨集之外,會將程式的篇幅大大增長。
函式:函式的程式碼只出現在一個位置,每次使用函式時,就呼叫那個位置的程式碼。
2.執行速度:
巨集:引數巨集的執行速度會比函式快,因為不需要引數壓棧/出棧操作。
函式:存在呼叫/返回的額外時間。
3.括號內的操作符 優先順序
巨集:巨集引數的求值是在所有周圍表示式的上下文環境裡,除非它們加上括號(儘量能加就加,不要吝嗇括號),否則鄰近操作符的優先順序可能會產生不可預料的結果。(下面文章會有程式碼演示)
函式:函式引數只在被呼叫前求值一次,它的結果傳遞給引數,並不會導致多種求值過程。表示式的求值結果更容易預測
4.引數求值:
巨集:引數每次用於巨集定義時,他們都將重新求值,由於多次求值,具有副作用的引數可能會產生不可預料的結果(下面文章會有程式碼演示
函式:引數在被呼叫前只求值一次,在函式中多次使用引數並不會導致多種求值過程,引數的副作用並不會造成任何特殊問題。
5.引數型別:
巨集:巨集宇型別無關,只要對引數的操作是合法的(比如比大小,只要能用>作比較就可以實現),它可以使用於任何引數型別。
函式:函式的引數需要定義型別,如果引數的型別不同,就要使用不同的函式,及時它們的執行任務是相同的。
———————————————————————————————————————————————————

巨集的一些簡單用法介紹

巨集的申明方式:
#define name(x) x*x
注意:引數列表的左括號必須與name緊鄰。
如果兩者之間有空白,引數列表會被解釋為x*x中的一部分。
使用巨集的一些需要注意的地方(坑):
1.括號問題
如 #define square(x) x*x
    一般使用square(5); 沒問題,因為文字將會替換為5*5,結果為25.
    但是使用square(2+1); 我們來試一下,並預測一下結果
int main()
{
	printf("%d\n",square(2+1));
	return 0;
}
   如果你認為答案是9,那就進坑了
   實際在編譯過程中,已經將巨集文字替換,priintf("%d\n",2+1*2+1);
   現在看起來一目瞭然,結果是5。
2.#和##在巨集 中的使用
使用#把一個巨集引數轉化其對應的字串。
例:
	int i = 10;
#define PRINT(FORMAT,VALUE) printf("the value of\
 " #VALUE " is "FORMAT"\n",VALUE);
	PRINT("%d",i+3);

	return 0;


##把兩邊的符號合為一個符號
例:
#define ADD_TO_SUM(num,value) sum##num += value;
	int sum5 = 0;
	int ret = ADD_TO_SUM(5,10);
	printf("%d",ret);

將num=5賦值後,此時的sum##num相當於,sum5 += 10;