C++:预处理功能
預(yù)處理功能介紹
為有助于執(zhí)行編譯過程,經(jīng)常可以使用一些預(yù)處理命令。每條預(yù)處理命令都具備一定的預(yù)處理功能。 常用的預(yù)處理命令有以下三項:
1.宏定義命令
2.文件包含命令
3.條件編譯命令。
預(yù)處理命令具有以下特點:
1.在左邊加 # 號,作為標(biāo)志。
2.一般獨占一行。
3.預(yù)處理命令不是編程語句,因此句末不加分號。
4.在正常編譯過程之前作為預(yù)備動作而執(zhí)行,編譯過程結(jié)束后不占用存儲空間。
宏定義命令
·簡單宏定義
例如:
#define PI 3.14159
#define SIZE 80
宏定義命令被執(zhí)行時,用字符串替代宏名,例如用3.14159替代PI,用80替代SIZE,等。
[例1]計算圓周長和面積。
#define PI 3.14159
void main( )
{
double circum, area, r = 3;
circum = 2 * PI * r;
area = PI * r * r;
}
宏定義命令被執(zhí)行時,不作語法檢查。例如,用戶希望將EXEC宏替代整句語句(例如int i=5;),使用以下宏:
#define EXEC int i=5
其中遺漏了分號(int i=5;才是完整語句),但因不作語法檢查,因此查不出以上錯誤,而直到編譯系統(tǒng)將其它使用該宏的語句進(jìn)行編譯時才能發(fā)現(xiàn)錯誤。
·帶參數(shù)宏定義
注意:帶參數(shù)宏定義并不是函數(shù)
例如:
#define ADD(x,y) x+y
[例1]計算兩數(shù)之和。
#include
#define ADD(x,y) x+y
void main( )
{
int a(40), b(50); //將a、b分別初始化為40、50
int sum = ADD(a, b); //宏替代結(jié)果為int sum = a + b;
cout<
}
運行結(jié)果:
90
宏替代的操作服從于運算符的優(yōu)先級,見下例:
[例2]計算數(shù)的平方。
// macro_3.cpp
// Attention in defining macro
// From Lv's book, p.85
#define SQ(x) x*x
#include
void main()
{
int a = 2, b = 3;
cout << SQ(a+b) << endl;
//由于乘法運算符優(yōu)先級高于加法運算符,所以執(zhí)行a+b*a+b
}
/* Result:
should be 25, but we get
a+b*a+b=11 */
問題出在優(yōu)先級,應(yīng)改正如下:
// macro_1.cpp
#define SQ(x) (x)*(x)
#include
void main()
{
int a = 2, b = 3;
cout << SQ(a+b) << endl; //即(a+b)*(a+b)
}
/* Result:
25 */
請注意:宏不是函數(shù)(子程序)!
宏與函數(shù)的區(qū)別:宏節(jié)省時間但占用空間;函數(shù)節(jié)省空間但增加時間!
文件包含
如果以上所述的宏定義語句很多,則可將它們包含于一個單獨的文件中,例如 "macros.h" 中。此macros.h文件內(nèi)容例如可為:
// macros.h
#define MAX 32 #define sq(n) (n)*(n)
#define PI 3.14159
… …
此時用戶程序可簡化為只包含以下一條語句:
#include "macros.h"
即可執(zhí)行以上所有宏命令。
以上macros.h稱為頭文件(header files)(或稱包含文件,include files)。
其中系統(tǒng)所定義的頭文件名稱(例如iostream.h)使用尖括弧< >將頭文件名稱iostream.h包括起來,系統(tǒng)就根據(jù)這點到系統(tǒng)的文件夾中去調(diào)用;而用戶自定義的頭文件則用雙引號" "將頭文件名稱包括起來,例如"macros.h"。系統(tǒng)就根據(jù)這點到用戶程序的文件夾中去調(diào)用。請注意區(qū)別此點。
C++語言系統(tǒng)中有很多頭文件,它們除包含宏替代定義語句外,更主要包含函數(shù)原型和類的定義或類的接口,及其所用各種數(shù)據(jù)類型的全局變量、外部靜態(tài)變量和常量的定義。
條件編譯
條件編譯命令的功能是規(guī)定某些語句(或某個程序塊)在一定條件下才參加編譯,否則跳過不予理睬。
其主要用途為:防止遺漏定義或避免重復(fù)定義;以及在測試時增加某些測試語句,以實現(xiàn)調(diào)試跟蹤的目的。本節(jié)主要講防止遺漏定義或避免重復(fù)定義的功能。
其格式為:
#ifdef (常量表達(dá)式)(或 #if defined(常量表達(dá)式))
[條件編譯語句]
#endif
或
#ifndef (常量表達(dá)式)(或 #if not defined(常量表達(dá)式))
[條件編譯語句]
#endif
以上語句中,當(dāng)常量表達(dá)式無定義時,就編譯兩個條件編譯命令#ifdef(或#ifndef)與#endif之間的條件編譯語句。
條件編譯命令也可表達(dá)如:
#if (常量表達(dá)式)
[條件編譯語句]
#endif
此時如常量表達(dá)式非零,則滿足編譯條件,編譯兩個條件編譯命令#if與#endif之間的條件編譯語句。
現(xiàn)在講解其避免遺漏定義和避免重復(fù)定義的功能:
以下使用 #ifndef MAX,此即(# if not defined MAX)或(#if !defined MAX)
例題:
// test_ifndef_1.cpp
// To prevent the missing of macro definition
#include <iostream.h>
#ifndef MAX
#define MAX 32
#endif
void main()
{
cout << "MAX is " << MAX << endl;
}
/* Result:
MAX is 32 */
上例中MAX沒有定義,所以執(zhí)行條件編譯語句#define MAX 32語句。
此例中MAX已經(jīng)定義過了,故不執(zhí)行條件編譯語句]2例[
// test_ifndef_2.cpp
// To prevent the missing of macro definition
#include <iostream.h>
#define MAX 10
#ifndef MAX
#define MAX 32
#endif
void main()
{
cout << "MAX is " << MAX << endl;
}
/* Result:
MAX is 10 */
上例中MAX已被定義為等于10,所以不執(zhí)行條件編譯語句#define MAX 32語句。再說,如果真是執(zhí)行了條件編譯語句#define MAX 32語句,必將會出現(xiàn)如下警告:
warning: 'MAX' : macro redefinition
test_ifndef_2.cpp(6) : see previous definition of 'MAX'
再看避免重復(fù)包含頭文件的例子:
[例3]防止重復(fù)包含頭文件。
設(shè)已有頭文件如下:
// ifndef.h
// To avoid the duplication of include files
#if !defined(_IFNDEF_H)
#define _IFNDEF_H
int var=1; //global variable
#endif //_IFNDEF_H
用戶應(yīng)用程序如下:
// test_ifndef_3.cpp
// To prevent the duplication of macro definition
#include <iostream.h>
#include "ifndef.h"
#include "ifndef.h" //看似重復(fù)包含,實則不予執(zhí)行
void main()
{
cout << "變量var = " << var << endl;
}
/* Result:
變量var = 1
*/
此程序中雖然多了一句#include "ifndef.h",但第二句不起作用。原因在于頭文件中使用了條件編譯功能。怎么知道重復(fù)包含的第二句不起作用?因為如果包含第二句的話,將會出錯。如下:
// test_ifndef_4.cpp
// The error of the duplication of macro definition
#include <iostream.h>
int var=1;
int var=1;
void main()
{
cout << "變量var = " << var << endl;
}
/* Result : Not working
error C2374: 'var' : redefinition; multiple initialization
*/
在任何頭文件中,都必須使用上述條件編譯語句以便避免重復(fù)包含。在有些頭文件中,也可能使用語句#pragma once,只要在頭文件的初始部分加入這條指令,就能夠保證頭文件只被編譯一次。有時同時使用條件編譯語句#if !defined(_IFNDEF_H)和#pragma語句。
?
總結(jié)
- 上一篇: 其实企业的C++人最清楚企业的问题
- 下一篇: 程序员应学习蜡笔小新的心态