標籤:
預先處理的概念
以"#"號開頭的就是預先處理命令,在來源程式中這些命令都放在函數之外,而且一般都放在源檔案的前面,它們稱為預先處理部分 所謂預先處理是指在進行編譯的第一遍掃描(詞法掃描和文法分析)之前所作的工作,預先處理是C語言的一個重要功能,它由預先處理程式負責完成.當對一個源檔案進行編譯時間,系統將自動引用預先處理程式對來源程式中的預先處理部分作處理,處理完畢自動進行對來源程式的編譯 C語言提供了多種預先處理功能,如:宏定義、檔案包含、條件編譯等.合理地使用預先處理功能編寫的程式便於閱讀、修改、移植和調試,也有利於模組化程式設計。
宏及條件編譯:
宏的概念
被定義為"宏"的表示符稱為"宏名"。在編譯預先處理時,對程式中所出現的"宏名",都用宏定義中的字串去代換,這稱為"宏代換“或”宏展開" 宏定義是由來源程式中的宏定義命令完成的,宏代換是由預先處理程式自動完成的.在C語言中,"宏分為有參和無參數兩種" 無參宏的宏名後不帶參數,其定義的一般形式為: #define 標示符 字串 # 表示這是一條預先處理命令,凡是以"#"開頭的均為預先處理命令 define 為宏定義命令 標示符 為所定義的宏名 字串 可以是常數、運算式、格式串等
注意事項:
1.習慣上宏名用大寫字母表示,以便於與變數區別,但也允許用小寫字母 2.宏定義時用宏名來表示一個字串,在宏展開時又以該字串取代宏名,這隻是一種簡單地代換,字串中可以含任何字元,可以是常量,也可以是運算式,預先處理程式對它不作任何檢查.如有錯誤,只能在編譯已被宏展開後的來源程式時發現 3.宏定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換 4.宏定義必須寫在函數之外,其範圍為宏定義命令到來源程式結束.如要終止其範圍可使用 #undef命令 5.宏定義允許嵌套 #define R 4 #define PI 3.14 #define AREA R*PI //嵌套定義 6.宏名在來源程式中若用 "" 括起來,則預先處理程式不對其做宏代換 7.可用宏定義表示資料類型,使書寫方便 #define INT int INT a; a=10; //相當於用宏給 int 起了一個別名 #define P struct Person P{ int age; }; P p1= {24};
有參宏的定義方法和使用
C語言允許宏帶有參數.在宏定義中的參數稱為形式參數,在宏調用中的參數稱為實際參數 對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去代換形參 帶參宏定義的一般形式為: #define 宏名(形參1,形參2...) 字串 帶參宏調用的一般形式為: 宏名(實參1,實參2..); 例: #define SUM(a) a+a int result=SUM(3); printf("%d \n",result);
有參宏使用的注意事項
1.帶參宏定義中,形參之間可以出現空格,但是宏名和形參表之間不能有空格出現 2.在帶參宏定義中,形式參數不分配記憶體單元,因此不必作類型定義.而宏調用中的實參是具體的值.要用它們去代換形參,因此必須作類型說明.這是與函數中的情況不同的.在函數中,形參和實參是兩個不同的量,各有自己的範圍,調用時要把實參值賦予形參,進行"值傳遞"。而在帶參宏中,只是符號代換,不存在值傳遞的問題 3.在宏定義中的形參是標識符,而宏調用中的實參可以是運算式 4.在宏定義中,字串內的形參通常要用括弧括起來以避免出錯,在上例中的宏定義中(y)*(y)運算式的y都用括弧括起來,因此結果是正確的 例如:#define SUM(x,y) (x)*(y)+(x)+(y) 5.宏定義也可用來定義多個語句,在宏調用時,把這些語句又代換到來源程式內 例:#define M3(m,n) m=a+2;n=a*2;
應用:
定義一個有參宏,求最大值 #define MAX(a,b) a>b?a:b
同樣定義別名時 #define 和 typedef的區別
宏定義只是簡單地字串代換,宏是在預先處理完成的,而typedef是在編譯時間處理的,它不是作簡單地代換,而是對類型說明符重新命名.被命名的標識符具有類型定義說明的功能 例: #define PIN1 int* typedef int *PIN2; PIN1 a,b;//這裡的a 是 int* 而b是int PIN2 a1,b1;// 這裡a1,b1 都是int* 產生差異的原因在於 一個是預先處理階段 一個是編譯階段
條件編譯的概念和優點:
1.為什麼要使用條件編譯
1)按不同的條件去編譯不同的程式部分,因而產生不同的目標代碼檔案.有利於程式的移植和調試 2)條件編譯當然也可以用條件陳述式來實現.但是用條件陳述式將會對整個來源程式進行編譯,生產的目標代碼程式很長,而採用條件編譯,則根據條件只編譯其中的程式段1或程式段2,生產的目標程式較短
2. #if-#else條件編譯指令
格式: #if 常量運算式 程式段1 #elif 常量運算式 程式段2 #else 程式段3 #endif 缺點: 判斷的依據是宏定義中的資料,而不是編譯器中的
3 #ifdef用來半段某個宏是否定義,定義為ture
例: int a =0; #ifdef DEBUG a =10; #else a=1000; #endif
4. #ifndef 用來判斷某個宏是否定義,沒定義為true
當使用條件編譯指令調試BUG,類似於JAVA中的LOG管理
條件:
DEBUG1 = 1 顯示調試資訊
DEBUG1 = 0 不顯示調試資訊
#define DEBUG=1 #if DEBUG1==1 #define Log(format,...) printf(format,## __VA_ARGS__); #elif DEBUG1==0 #define Log(format,...) #else #define Log(format,...) #endif 使用 Log("XXXXX-->",10); //format 代表形參 ...表示可變參數 也類似於java中的泛型 //##標示可以有參數也可以沒有參數 ,如果沒有##就至少有一個參數
C語言預先處理命令