鍍金池/ 教程/ C/ 預(yù)處理器
動(dòng)態(tài)內(nèi)存
類(lèi)和對(duì)象
接口 (抽象類(lèi))
結(jié)構(gòu)體
循環(huán)的類(lèi)型
函數(shù)
數(shù)字
日期和時(shí)間
基本語(yǔ)法
多態(tài)
數(shù)據(jù)抽象
注釋
命名空間
字符串
預(yù)處理器
決策語(yǔ)句
修飾符的類(lèi)型
鍙橀噺綾誨瀷
基本輸入輸出
操作符
數(shù)組
模板
多線程
繼承
Web 編程
信號(hào)處理
指針
存儲(chǔ)類(lèi)型
概述
引用
常量
異常處理
開(kāi)發(fā)環(huán)境
重載
變量作用域
數(shù)據(jù)類(lèi)型
數(shù)據(jù)封裝
文件和流

預(yù)處理器

預(yù)處理器是指令,在實(shí)際編譯開(kāi)始之前,預(yù)處理器會(huì)給編譯器指令來(lái)預(yù)處理需要編譯的信息。

所有的預(yù)處理指令以開(kāi)頭,可能在預(yù)處理指令行之前出現(xiàn)的只有空白字符。預(yù)處理指令是不是 C++ 語(yǔ)句,所以它們不會(huì)以分號(hào)(;)結(jié)束。

你已經(jīng)在所有的例子中都看到了 #include 指令。這個(gè)宏用于將頭文件包含到源文件。

還有許多 C++ 支持的預(yù)處理指令,如#include,#define, #if, #else, #line 等等。下面我們來(lái)看一些重要的指令:

define 處理器

#define 處理指令用來(lái)創(chuàng)建符號(hào)常量。這個(gè)符號(hào)常量被稱(chēng)為。指令的一般形式是:

    #define macro-name replacement-text 

當(dāng)這一行出現(xiàn)在一個(gè)文件中時(shí),在程序被編譯之前,該文件中的所有后續(xù)出現(xiàn)的 macro-name 將會(huì)被 replacement-text 替換掉。 例如:

    #include <iostream>
    using namespace std;

    #define PI 3.14159

    int main ()
    {

    cout << "Value of PI :" << PI << endl; 

    return 0;
    }

現(xiàn)在,讓我們對(duì)這個(gè)代碼進(jìn)行預(yù)處理來(lái)看一看結(jié)果。假設(shè)我們有源代碼文件,那么我們用 -E 選項(xiàng)編譯它并重定向結(jié)果到 test.p?,F(xiàn)在,如果你查看 test.p,會(huì)發(fā)現(xiàn)里面有大量的信息,并且你會(huì)在底部發(fā)現(xiàn)值已經(jīng)被替換了,如下所示:

    $gcc -E test.cpp > test.p

    ...
    int main ()
    {

    cout << "Value of PI :" << 3.14159 << endl; 

    return 0;
    }

函數(shù)宏

你可以用#define定義一個(gè)帶有如下參數(shù)的宏:

    #include <iostream>
    using namespace std;

    #define MIN(a,b) (((a)<(b)) ? a : b)

    int main ()
    {
       int i, j;
       i = 100;
       j = 30;
       cout <<"The minimum is " << MIN(i, j) << endl;

    return 0;
    }

如果我們編譯并運(yùn)行上述代碼,將會(huì)產(chǎn)生以下結(jié)果:

    The minimum is 30

條件編譯

有幾種不同的指令,其可用于有選擇的編譯程序源代碼的一部分。這個(gè)過(guò)程被稱(chēng)為條件編譯。

條件預(yù)處理器結(jié)構(gòu)很像 if 選擇結(jié)構(gòu)。思考下面的預(yù)處理代碼:

    #ifndef NULL
       #define NULL 0
    #endif

你可以編譯一個(gè)用于調(diào)試的程序,并且可以用單個(gè)宏打開(kāi)或關(guān)閉調(diào)試開(kāi)關(guān),如下所示:

    #ifdef DEBUG
       cerr <<"Variable x = " << x << endl;
    #endif

如果符號(hào)常量 DEBUG 定義在#ifdef DEBUG指令之前,那么程序中的 cerr 語(yǔ)句會(huì)被編譯。你可以使用#if 0語(yǔ)句注釋掉程序的一部分,如下所示:

    #if 0
       code prevented from compiling
    #endif

我們來(lái)用下面的例子試一下:

    #include <iostream>
    using namespace std;
    #define DEBUG

    #define MIN(a,b) (((a)<(b)) ? a : b)

    int main ()
    {
       int i, j;
       i = 100;
       j = 30;
    #ifdef DEBUG
       cerr <<"Trace: Inside main function" << endl;
    #endif

    #if 0
       /* This is commented part */
       cout << MKSTR(HELLO C++) << endl;
    #endif

       cout <<"The minimum is " << MIN(i, j) << endl;

    #ifdef DEBUG
       cerr <<"Trace: Coming out of main function" << endl;
    #endif
    return 0;
    }

如果我們編譯并運(yùn)行上述代碼,將會(huì)產(chǎn)生以下結(jié)果:

    Trace: Inside main function
    The minimum is 30
    Trace: Coming out of main function

和 ## 操作符

在 C++ 和 ANSI/ISO C 中###預(yù)處理器操作符是可用的。

操作符會(huì)將要替代的文本符號(hào)轉(zhuǎn)換成用雙引號(hào)引起來(lái)的字符串。

思考下面的宏定義:

    #include <iostream>
    using namespace std;

    #define MKSTR( x ) #x

    int main ()
    {
    cout << MKSTR(HELLO C++) << endl;

    return 0;
    }

如果我們編譯并運(yùn)行上述代碼,將會(huì)產(chǎn)生以下結(jié)果:

    HELLO C++

讓我們來(lái)看看它是如何工作的。

這很容易理解,C++ 預(yù)處理器將下面一行代碼:

    cout << MKSTR(HELLO C++) << endl;

轉(zhuǎn)變成了下面這一行的代碼:

    cout << "HELLO C++" << endl;

##操作符是用來(lái)連接兩個(gè)符號(hào)的。

例子如下所示:

    #define CONCAT( x, y )  x ## y

當(dāng) CONCAT 出現(xiàn)在程序中時(shí),它的參數(shù)會(huì)被連接起來(lái),并用其來(lái)取代宏。例如,CONCAT(HELLO,C++),在程序中會(huì) “HELLO C++” 替代。例子如下所示。

    #include <iostream>
    using namespace std;

    #define concat(a, b) a ## b
    int main()
    {
       int xy = 100;

       cout << concat(x, y);
       return 0;
    }

如果我們編譯并運(yùn)行上述代碼,將會(huì)產(chǎn)生以下結(jié)果:

    100

讓我們來(lái)看看它是如何工作的。

這很容易理解,C++ 預(yù)處理器將下面一行代碼:

    cout << concat(x, y);

轉(zhuǎn)換成了下面這一行的代碼:

     cout << xy;

C++ 預(yù)定義的宏

C++ 提供了許多預(yù)定義的宏,如下所示:

描述
__LINE__ 編譯過(guò)后,其包含了當(dāng)前程序行在程序內(nèi)的行號(hào)
__FILE__ 編譯過(guò)后,其包含了當(dāng)前程序的程序名
__DATE__ 其包含了由源文件轉(zhuǎn)換為目標(biāo)代碼的日期,該日期是格式為 月/日/年 的字符串文本
__TIME__ 其包含了源文件編譯的時(shí)間,該時(shí)間是 時(shí):分:秒 形式的字符串文本

我們來(lái)看一個(gè)展示上面宏的例子:

    #include <iostream>
    using namespace std;

    int main ()
    {
    cout << "Value of __LINE__ : " << __LINE__ << endl;
    cout << "Value of __FILE__ : " << __FILE__ << endl;
    cout << "Value of __DATE__ : " << __DATE__ << endl;
    cout << "Value of __TIME__ : " << __TIME__ << endl;

    return 0;
    }

如果我們編譯并運(yùn)行上述代碼,將會(huì)產(chǎn)生以下結(jié)果:

    Value of __LINE__ : 6
    Value of __FILE__ : test.cpp
    Value of __DATE__ : Feb 28 2011
    Value of __TIME__ : 18:52:48