目錄
(本章節中例子都是用 VS2005 編譯調試的)
宏
不帶參數的宏 -----------------------------------------------------
形式:
#define 宏名稱 替換主體
注意:
- 替換主體中可以有空格空格不是替換主體的一部分(這也很好理解,因為編程的時候執行語句也一般是忽視中間的空格的就好比 a = 3; 與 a=3;是等價的一樣 ),例如 #define SIX 2 *3 (等價於 #define SIX 2*3)
- 但是替換主體的內容還是要遵照一定的規定表達式的數據和操作符中間可以有空格但是一個數據中不能存在 (比如不能這樣定義宏 #define PI 3 .14 或者 #define PI 2 2)
例子:

1 #define PI 3.14 //下文出現 PI 的時候都用 3.14 去替換 2 #define SIX 3+3 //下文出現 SIX 的時候都用 3+3 去替換 3 4 void mian() 5 { 6 int x; 7 x = PI; //等價於 x = 3.14 8 x = SIX * 5 //這里注意了,x的值為 18 而不是 30 9 //因為宏只做簡單替換也就是這里等價於 x = 3+3*5 所以x值當然是18了 10 }
帶參數的宏 --------------------------------------------------------
形式:
#define 宏名稱(參數列表) 替換主體
定義:
類函數宏的定義中,用圓括號括起來一個或多個參數,隨后這些參數出現在替換部分
例子:
1 #define MAX(x,y) (x>y? x: y)
#運算符 ----------------------------------------------------------
形式:
#define 宏名稱(參數列表) 替換主體
定義:
#符號把語言符號字符串化(也就是 用 "宏參數" 去替換替換主體中的 #宏參數 )
例子:
1 //定義宏 2 #define PSQR(x) cout<<"it is " #x<<endl; 3 4 //然后調用PSQR 5 PSQR(x) //輸出的結果為: it is x
##運算符 --------------------------------------------------------
形式:
#define 宏名稱(參數列表) 替換主體
作用:
- ##后面緊緊跟着的是宏參數
- 這個語言符號組合成單個語言符號,也就是把替換主體與宏參數結合成一個語言符號
- 宏參數在編譯階段只簡單看成字符或字符串沒有其他含義
例子:

1 // 例1 ---- 2 //定義宏 3 #define XNAME(n) a##n 4 5 //調用宏 6 char a1 = 'x'; 7 cout<<XNAME(1)<<endl; //輸出結果為: x 8 9 10 11 // 例2 ---- 12 //定義宏 13 #define XNAME(n) a##n = '6' 14 15 //調用宏 16 char a1 = 'x'; 17 XNAME(1);
取消宏定義#undef -------------------------------------------------
形式:
#undef 宏名稱
作用:
取消定義過的宏
例子:
1 #define TWO 2 2 #undef TWO // 取消宏定義在以后的地方TWO這個宏就不存在了
預定義宏 -----------------------------------------------------------
- 本機日期 __DATE__
- ‘1’為遵循c標准 __STDC__
- 文件名 __FILE__
- 為本機環境設置1,否則為0 __STDC_HODTED__
- 行號 __LINE__
- 為c99時設置為1999901L __STDC
- 本機時間 __TIME__
雜項 ---------------------------------------------------------------
作用域:
作用域是文件,或者直到遇到undef為止
注意事項:
- 宏的名字不能有空格,並用圓括號括住每個參數,例如#define f (x) ((x)+1)盡管你想表達的是f(x)用((x)+1)的意思但是結果編譯器卻認為是f用(x)((x)+1)代替
- 宏不是函數,宏在編譯時期只是做簡單的替換
-
宏不是類型定義,因為它只作簡單替換,對於類型定義最好用typedef來完成,比如#define F int*,與typedef int* F時用F去聲明變量時, F a,b.宏只能做到把第一個變量聲明成指針,而后一卻是聲明變量.而typedef可以把兩個都聲明成指針(關於typedef)
- 如果使用宏,加快程序運行速度,首先確定是否會引起重大差異
優缺點:
預處理器不對宏進行計算,而只是簡單進行字符串替換,宏不檢查其中變量類型,但宏會產生內聯代碼,而且比內聯函數花費的時間多,比函數占的內存更大
其他的預編譯
#line --------------------------------------------------------------
作用
- #line命令是用於更改__LINE__ 和 __FILE__變量的值. 文件名是可選的. __LINE__ 和 __FILE__ 變量
- 描述被讀取的當前文件和行. 命令 <例:#line 10,“cool,cpp”//把行號重置為10,文件名為“cool.cpp”>
#error ------------------------------------------------------------
作用
使預處理器發出一條錯誤消息,該消息包含指令文本
條件編譯 -----------------------------------------------------------
說明:
#ifdef ,#else , #elif , #ifndef , #if 和 #endif (用法與if…else相似)
作用:
可以防止頭文件被重復定義
例子:
防止頭文件被多次定義的例子:

1 //防止頭文件被多次定義 2 //以 iostream 頭文件為例子 3 // 方法1 ---- 4 #ifndef __IOSTREAM_H__ 5 #define __IOSTREAM_H__ 1 6 #include <iostream> 7 #endif 8 9 10 // 方法2 ---- 11 #pragma once 12 #include <iostream> 13 14 15 // 方法3 ---- 16 #if !defined(__IOSTREAM_H__) 17 #define __IOSTREAM_H__ 1 18 #include <iostream> 19 #endif 20 //一般不提倡這么用就是了
再來看一個來自於微軟技術資源庫的例子:

1 // 例1 -- 2 #if defined(CREDIT) //defined(CREDIT) 代表的是是否定義過CREDIT這個宏 3 //如果定義過返回真,沒定義返回假 4 credit(); 5 #elif defined(DEBIT) 6 debit(); 7 #else 8 printerror(); 9 #endif 10 11 12 //例子2 -- 13 #if DLEVEL > 5 //#if 后面也可以接條件表達式 14 #define SIGNAL 1 15 #if STACKUSE == 1 16 #define STACK 200 17 #else 18 #define STACK 100 19 #endif 20 #else 21 #define SIGNAL 0 22 #if STACKUSE == 1 23 #define STACK 100 24 #else 25 #define STACK 50 26 #endif 27 #endif 28 #if DLEVEL == 0 29 #define STACK 0 30 #elif DLEVEL == 1 31 #define STACK 100 32 #elif DLEVEL > 5 33 display( debugptr ); 34 #else 35 #define STACK 200 36 #endif
這里就簡單的讓你了解下條件編譯的運用,例子的鏈接為:http://technet.microsoft.com/zh-cn/library/ew2hz0yd(v=vs.110)
雜項 ---------------------------------------------------------------
“預編譯命令”的兩大步驟:
- 先進行一次“預編譯對所有預編譯命令進行處理,把#include包含的頭文件內容調出來放到#include命令的位置
- 進行正式編譯工作,得到目標文件(后綴為obj)(不要把符號常量與變量混淆,符號常量只是一個符號,不占存儲單元,習慣上,符號常量名用大寫,變量名用小寫,以好區分,使用符號常量好處①含義清楚;②在需要時可改)