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