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