1. 巨集定義指令
1) 定義變數與命令(避免幻數)
在巨集定義命名時,盡量能清楚的表明功能,大寫(不能以__開頭易與內建巨集衝突)
2) 定義巨集函式
#define max(a, b) a >b ? a : b
int num = max(6, 5);à6 > 5 ? 6 : 5
用編譯時間換記憶體空間的是巨集函式
用記憶體空間換執行空間的是內斂(內嵌)函式
3) 自定義函式與巨集函式的區別
巨集函式省去了分配、釋放棧幀,傳參、傳返回值等一系列工作,效率更高;但巨集函式不做語法檢查,不安全,且實現不了複雜的功能。
自定義函式更安全,但效率低。
4) 內建巨集定義
__line__ 顯示行號
__func__ 顯示函式名
__time__ 顯示時間
__data__ 顯示日期
5) typedef與#define的區別
l執行時間不同
關鍵字typedef在編譯階段有效,由於是在編譯階段,因此typedef有型別檢查的功能。
#define則是巨集定義,發生在預處理階段,也就是編譯之前,它只進行簡單而機械的字串替換,而不進行任何檢查。
l功能有差異
typedef用來定義型別的別名,定義與平台無關的資料型別,與struct的結合使用等。
#define不只是可以為型別取別名,還可以定義常量、變數、編譯開關等。
l作用域不同
#define沒有作用域的限制,只要是之前預定義過的巨集,在以後的程式中都可以使用。
typedef有自己的作用域。
6) 列舉與#define的區別
l 列舉常量是實體中的一種,但巨集不是實體;
l 列舉常量屬於常量,但巨集不是常量;
l 列舉常量具有型別,但巨集沒有型別,列舉變數具有與普通變數相同的諸如作用域、值等性質,但巨集沒有,巨集不是語言的一部分,它是一種預處理替換符。列舉型別主要用於限制性輸入,例如,某個函式的某引數只接受某種型別中的有限個數值,除此之外的其它數值都不接受,這時候列舉能很好地解決這個問題。能用列舉盡量用列舉,否則在除錯的時候你是看不到當時的值的。
l 用巨集去定義乙個變數如果你定義了乙個相同的變數那麼要看誰在前面,如果巨集在前面變數會產生編譯錯誤,而且這個錯誤很難查詢,如果那個巨集隱藏的很深的話。如果你定義的變數在前那麼更可怕了,直接沒有錯誤,但是巨集定義被自定義的變數悄悄替換了。用列舉定義的話不管你定義的順序前後關係怎樣都會產生重複定義的錯誤。從上面的舉例來看列舉比巨集好用的多。巨集還有乙個特性是沒有作用域,這裡的作用域是指巨集定義以後的**都可以使用這個巨集。巨集可以被重複定義這個可能導致巨集的值被修改。所以建議不要用巨集去定義整形的變數,用列舉或者const。又會有用const還是列舉呢,世界一向如此糾結,列舉只能表示整形,const可以修飾任何型別。整形的情況下如果你要定義幾種有關係的數值那麼用列舉,否則用const。
2. 條件編譯指令
#ifdef、#ifndef、#endif
防止標頭檔案重複包含帶來的重複定義
#ifdef、#ifndef主要用於防止重複包含。我們一般在.h標頭檔案前面加上這麼一段:
//標頭檔案防止重複包含
#ifndef funca_h
#define funca_h
//標頭檔案內容
#end if
這樣,如果a.h包含了funca.h,b.h包含了a.h、funca.h,重複包含,會出現一些type redefination之類的錯誤。
#if defined等價於#ifdef; #if !defined等價於#ifndef
編譯預處理
所謂編譯預處理,就是在c源程式的編譯之前,由編譯預處理程式對這些編譯預處理命令進行處理的過程。最常見的就是常量的替換。編譯預處理按功能可以分為巨集定義,檔案包含和條件編譯三類。編譯預處理命令以 開頭,下面進行詳細說明 一.巨集定義與符號常量 1.無參巨集定義 define 識別符號 字串 1 巨集名...
編譯預處理
1 定義常量與命令 避免幻數 定義巨集時,避免以 開頭,以防與內建巨集定義衝突。巨集和列舉的區別 a.列舉常量是實體常量中的一種,但巨集不是實體 b.列舉常量屬於常量,但巨集不是常量 c.列舉常量具有型別,但巨集沒有型別。列舉型別主要用於限制性輸入,巨集只是預處理替換符 d.列舉只可以表示整型,巨集...
編譯預處理
我們知道在編譯過程中的預處理階段會進行標頭檔案展開,巨集替換以及條件編譯。1.標頭檔案展開 首先是標頭檔案展開,標頭檔案的前面都有 符號,其實是理指令。理指令是以 號開頭的 行。號必須是該行除了任何空白字元外的第乙個字元。後是指令關鍵字,在關鍵字和 號 之間允許存在任意個數的空白字元。整行語句構成了...