矇矇懂懂只知道 function跟 macro是類似的東西,不清楚具體的差異為何。
將以 C語言 來舉例,
通常在C語言寫程式中,第一行都是
井字符號 # 是給編譯器讀的(之後交由預處理器來處理),指示編譯器引入 stdio.h。
所以在 VSCode中寫C++時,會要求 #include stdafx.h,
即使最後輸出的結果是一樣的。
所有的預處理器 preprocessor 的命令都是由 # 開頭。
同樣是給編譯器看,但後面接著的參數命令有些編譯器看不懂。
所以這一項指示是隨著編譯器不同,所產生的結果也可能會有所不同。
具體來說是 當你按下此按鍵,他會自動幫你做一連串 預先設定好的動作或按鍵。
macro簡言之,就是進行代換,將複雜的東西代換成簡單的。
之後在主程式看到PI這個單字,就會將PI以3.14159取代。
在C語言中 macro進行了純文字的代換(textual replacement),概念就是大家都來一份。
而這裡也有一個很大的坑:
若在主程式中,下述能得到 25,看起來沒有問題
因為純文字替換後相當於這樣:
解決辦法為下,多了看起來有點冗餘的括號:
缺點:大家都要一份,頗占空間,產出檔案較大
備註:定義macro後,交給預處理器來處理,發生在編譯之前。
『咦,這裡有出現這一段、那裡也有出現這一段,出現的程式碼一模一樣。
啊,那我乾脆把這一段功能 寫成function好了,讓程式碼簡潔又易懂。』
就是一般寫在程式裡面的 function,概念就是同樣的空間,大家一起用。
給定輸入,使用同樣的邏輯,輸出返回結果(不一定要回傳結果)。
優點:節省空間呀,大家一起共用空間,產出的檔案較小
缺點:因為function初始化時CPU要進行 Stack push、pop的動作,缺點就是慢了些
但 "函式展開" 這句話過於抽象,
直觀解釋就是:像macro那樣 把function的程式碼 直接塞進程式碼行內,大家都來一份function。
使用時機:當function體積小、卻被頻繁使用時
優點:快速,大家都有一份,要用馬上就有得用,不用等push、pop
缺點:大家都要一份,很占空間,產出檔案較大。大量重複程式碼甚至會降低cpu快取命中率
備註:發生在進行編譯的時候。不同的編譯器會根據function使用到的次數、大小,來做不同的判斷、優化。
另外被內聯,等於你寫好的函式灰飛煙滅了、找不到函式的所在位置,除非前面有加上static、或是寫第二個相同名稱的function 前面不加inline。
將以 C語言 來舉例,
通常在C語言寫程式中,第一行都是
#include <stdio.h>
井字符號 # 是給編譯器讀的(之後交由預處理器來處理),指示編譯器引入 stdio.h。
The preprocessor replaces the line #include <stdio.h> with the textual content of the file 'stdio.h', which declares the printf() function among other things.雖語言相同、但因編譯器不同,
所以在 VSCode中寫C++時,會要求 #include stdafx.h,
即使最後輸出的結果是一樣的。
預處理器 preprocessor
在編譯前,編譯器就先做好的事前準備,諸如#include、#define等等。所有的預處理器 preprocessor 的命令都是由 # 開頭。
C語言預處理的指令12個:
而在 Objective-C 多個一個 #import
- #include
- #define
- #ifdef
- #ifndef
- #undef
- #error
- #line
- #if
- #else
- #elif
- #endif
- #pragma
編譯指示 directive (pragma)
上述第12項 #pragma 開頭的指示,同樣是給編譯器看,但後面接著的參數命令有些編譯器看不懂。
所以這一項指示是隨著編譯器不同,所產生的結果也可能會有所不同。
macro 巨集
在滑鼠、鍵盤裡面常聽到巨集的字眼,具體來說是 當你按下此按鍵,他會自動幫你做一連串 預先設定好的動作或按鍵。
譬如說,我自訂了一個功能鍵"施放絕招",按下之後鍵盤會在很短的時間內 向電腦發出 ↑ + ↑ + ↓ + ↓ + ← + ← + → + → + A + B + A + B 的連續按鍵。不然每次絕招都按到手殘廢了、絕招還不一定施展得出來。
macro簡言之,就是進行代換,將複雜的東西代換成簡單的。
#define PI 3.14159
之後在主程式看到PI這個單字,就會將PI以3.14159取代。
在C語言中 macro進行了純文字的代換(textual replacement),概念就是大家都來一份。
而這裡也有一個很大的坑:
# define Square(x) x*x
若在主程式中,下述能得到 25,看起來沒有問題
printf("\n %d", square(5));但如果是以下,卻會得到 11
printf("\n %d", square(3+2));
因為純文字替換後相當於這樣:
printf("\n %d", 3+2 * 3+2);
解決辦法為下,多了看起來有點冗餘的括號:
# define Square(x) ((x)*(x))優點:大家都有一份,要用馬上就有得用,快速
缺點:大家都要一份,頗占空間,產出檔案較大
備註:定義macro後,交給預處理器來處理,發生在編譯之前。
function 函式
『咦,這裡有出現這一段、那裡也有出現這一段,出現的程式碼一模一樣。
啊,那我乾脆把這一段功能 寫成function好了,讓程式碼簡潔又易懂。』
就是一般寫在程式裡面的 function,概念就是同樣的空間,大家一起用。
給定輸入,使用同樣的邏輯,輸出返回結果(不一定要回傳結果)。
優點:節省空間呀,大家一起共用空間,產出的檔案較小
缺點:因為function初始化時CPU要進行 Stack push、pop的動作,缺點就是慢了些
inline function 行內(內嵌、內聯)函式
inline 意思是把函式展開(function expand)。但 "函式展開" 這句話過於抽象,
直觀解釋就是:像macro那樣 把function的程式碼 直接塞進程式碼行內,大家都來一份function。
使用時機:當function體積小、卻被頻繁使用時
優點:快速,大家都有一份,要用馬上就有得用,不用等push、pop
缺點:大家都要一份,很占空間,產出檔案較大。大量重複程式碼甚至會降低cpu快取命中率
備註:發生在進行編譯的時候。不同的編譯器會根據function使用到的次數、大小,來做不同的判斷、優化。
另外被內聯,等於你寫好的函式灰飛煙滅了、找不到函式的所在位置,除非前面有加上static、或是寫第二個相同名稱的function 前面不加inline。
noinline 不要行內函式
有強制內聯方法,也有強制不要內聯的方法。
在function不想被內聯的時候使用。