深入浅出之预处理
預(yù)處理的輸出是“翻譯單元”,他是存放在內(nèi)存中的臨時(shí)文件,編譯器接受預(yù)處理輸出,并將源代碼轉(zhuǎn)換成包含機(jī)器語言指令的目標(biāo)文件。
1. 宏替換
1) 字符串替換
格式: #define 宏名 宏體
其中宏名與宏體均為字符串。預(yù)處理時(shí),將把程序中該宏定義之后的所有的宏名用宏體替換。
如:
#define PI 3.14宏替換的好處:
(1) 提高程序的可讀性
(2)易修改性好
2) 帶參數(shù)宏定義格式
#define 標(biāo)識(shí)符(參數(shù)表) 宏體
例如:
#define ? PI ? 3.14
 #define ? RAD ?2.0
 #define ? AREA return(PI*RAD*RAD)
 帶參數(shù)宏替換與函數(shù)區(qū)別:
(1) 時(shí)空效率不同,帶參數(shù)宏替換效率比函數(shù)高
(2) 宏雖然可以帶有參數(shù),但宏替換過程中不像函數(shù)那樣可以進(jìn)行參數(shù)值的計(jì)算、傳遞及結(jié)果返回等操作;宏替換只是簡(jiǎn)單的字符替換,不進(jìn)行計(jì)算。因此一些過程中不能用宏替換,比如遞歸調(diào)用;
?2.?書寫#define命令應(yīng)注意事項(xiàng)
 1) 宏名與宏體之間應(yīng)以空格相隔,所以宏名中不能含有空格
2) 宏名不能用引號(hào)括起來
比如#define “YES” 1 ?不進(jìn)行宏替換3) 較長的宏定義在一行中如果寫不下時(shí),可以在本行末尾使用反斜杠表示要續(xù)行
#define PRX printf(“ssss \ddddd”)4) ?對(duì)帶參數(shù)宏定義,宏體及其各個(gè)形參應(yīng)該用圓括號(hào)括起來
#include <QCoreApplication> //#include "test.h" #define f(x) x*x #define g(x) (x)*(x) #define h(x) ((x)*(x)) int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);qDebug("1:%d",f(2+2));qDebug("2:%d",g(2+2));qDebug("3:%d",h(2+2));return a.exec(); } 輸出: 1:8 【2+2*2+2=8】 2:16【(2+2)*(2+2)=16】 3:16【((2*2)*(2*2))=16】5) 宏定義不是C語言,不必再行末加分號(hào)
6)宏被定義后,一般不能再重新定義,而只能使用#undef命令終止該宏定義作用域(#undef 宏名)?
3. 文件包含
?格式1: #include “文件標(biāo)識(shí)符”
按這種格式定義時(shí),預(yù)處理程序首先在原來的源文件目錄中檢索該指定的文件;如果沒有找到,則按系統(tǒng)指定的標(biāo)準(zhǔn)方式檢索其他文件目錄,直至找到為止;
格式2:#include <文件標(biāo)識(shí)符>
按這種格式定義時(shí),預(yù)處理程序只在系統(tǒng)庫中尋找指定文件。
4. 條件編譯
 條件編譯可使同一源程序在不同的編譯條件得到不同的目標(biāo)代碼。
格式1:
#ifdef 標(biāo)識(shí)符程序段1#else程序段2#endif
 格式2:
 在工程的地方條件指示符#ifndef的最主要目的是防止頭文件的重復(fù)包含和編譯。
 格式3:
5. #define宏定義的缺點(diǎn)
?1)?無法對(duì)宏定義中的變量進(jìn)行類型檢查
define定義的變量,是Compile-Time時(shí)期的變量,系統(tǒng)在編譯時(shí)候,就將其全部替換,而不會(huì)對(duì)其變量進(jìn)行類型等屬性檢查,相對(duì)不是很安全,可能存在潛在的問題,而沒有發(fā)現(xiàn)。正因?yàn)槠鋬H僅是編譯時(shí)期替換,所以其定義的變量,是不會(huì)在運(yùn)行時(shí)候分配內(nèi)存的,不占用內(nèi)存空間。
2)?未加括號(hào)帶來的邊界效應(yīng)
由于宏定義的時(shí)候,其各個(gè)分量未加括號(hào),而在使用宏定義的時(shí)候,傳遞的參數(shù)是變量的表達(dá)式,然后經(jīng)過系統(tǒng)展開后,由于優(yōu)先級(jí)的原因,導(dǎo)致其結(jié)果不是你所希望的。
#define MUL(A,B) A*B而在使用的時(shí)候,這樣的調(diào)用:int a=1,b=2,c=3,d=0;d=MUL(a+b,c)經(jīng)過編譯時(shí)候展開,就變成了d=a+b*c而不是我們所希望的d=(a+b)*c[解決辦法]其解決辦法也很簡(jiǎn)單,就是給每個(gè)分量,都加上括號(hào),就可以避免此類問題即,在宏定義的時(shí)候,如此定義:#define MUL(A,B) ((A)*(B))6. #define替代方案?
1)?用const代替define來定義常量
const TYPE ValueName = value;
2)用inline代替define來定義函數(shù)
 define定義函數(shù)的最大缺點(diǎn)就是它只是簡(jiǎn)單替換,所以函數(shù)的參數(shù)可能會(huì)改變函數(shù)的行為。
 比如上面定義的max,如果有這么一段代碼:
int a = 5, b = 0;
 max(++a, b);? ? ? ? // a is incremented twice
 max(++a, b+10);? ? ? // a is incremented once
 可以看到對(duì)兩次調(diào)用,++a執(zhí)行的次數(shù)是不一樣的。而如果用inline,寫成如下形式:
inline int max(int a, int b) { return a > b ? a : b; }
7.C++ 中的預(yù)定義宏?
- 輸出當(dāng)前行的行號(hào)
預(yù)定義宏為:__LINE__,注意,是兩個(gè)下劃線。
 使用方法為:cout << “Current Line Number __LINE__ : ” << __LINE__ << endl;
- 輸出當(dāng)前文件名
預(yù)定義宏為:__FILE__
 使用方法為:cout << “Current File Name __FILE__ : ” << __FILE__ << endl;
- 輸出當(dāng)前文件編譯日期
解釋:形式為 month/day/year 的字符串,它表示把源文件轉(zhuǎn)換為目標(biāo)代碼的日期。
 預(yù)定義宏為:__DATE__
 使用方法為:cout << “Current Date __DATE__ : ” << __DATE__ << endl;
- 輸出當(dāng)前文件編譯時(shí)間
解釋:形式為 hour:minute:second 的字符串,它表示程序被編譯的時(shí)間。
 預(yù)定義宏為:__TIME__
 使用方法為:cout << “Current Time__TIME__ : ” << __TIME__ << endl;
 ?
總結(jié)
 
                            
                        - 上一篇: 三星532u3x怎么U盘启动 三星532
- 下一篇: 怎么修改电脑密码win7系统吗 win7
