C++ 速查手冊

14.2 - 巨集

前置處理器指令 #define 用來定義巨集 (macro) ,所謂的巨集是指文字的替換,舉例如下

#include <iostream>
#define DEMO 10

int main() {
    std::cout << DEMO << std::endl;
    
#undef DEMO

    //std::cout << DEMO << std::endl;
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:u1402_1.cpp
   功能:示範 C++ 的前置處理器
   作者:張凱慶*/

第 2 行定義了一個名為 DEMO 的巨集,這裡 DEMO 後空一格接整數 10 ,表示 DEMO 等於整數 10

#define DEMO 10

這意思是說,底下程式中只要出現 DEMO ,編譯前就會被置換成整數 10 ,像是程式中的這個部分

std::cout << DEMO << std::endl;

會變成

std::cout << 10 << std::endl;

然後才實際進行編譯,這樣的好處是可以把一些固定不變的字面常數用巨集取代,等同常數一樣。

下面的 #undef 指令則是取消 #define 的設定,因此底下第 9 行若是沒有註解化就會發生編譯錯誤。

編譯執行,結果如下

$ g++ u1402_1.cpp
$ ./a.out
10
$

巨集的另一個用途是取代簡單的函數,例如

#include <iostream>
#define Prints(arg) std::cout << #arg 

int main() {
    Prints(hello);
    std::cout << std::endl;
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:u1402_2.cpp
   功能:示範 C++ 的前置處理器
   作者:張凱慶*/

第 2 行定義的巨集 Prints(arg) 使用一個參數 arg ,後面的 arg 要加上 # 符號

#define Prints(arg) std::cout << #arg 

由於巨集是編譯前的文字替換,因此程式中這一行的 hello ,替換後等於字串 "hello"

Prints(hello);

編譯執行,結果如下

$ g++ u1402_2.cpp
$ ./a.out
hello
$

除了 # 在巨集中表示參數外,也可使用 ## 連結識別名稱,例如

#include <iostream>
#define F(n, a) int f##n() {return a;}
F(test, 0);
F(function, 1);
F(rrr, 2);

int main() {
    std::cout << ftest()<< std::endl;
    std::cout << ffunction()<< std::endl;
    std::cout << frrr() << std::endl;
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:u1402_3.cpp
   功能:示範 C++ 的前置處理器
   作者:張凱慶*/

第 2 行,巨集 F 有兩個參數 na ,呼叫 F 會產生以 f 開頭的新函數,新函數的識別字等於 fn ,然後回傳 a

#define F(n, a) int f##n() {return a;}

例如

F(test, 0);

因此就有了函數 ftest()

std::cout << ftest()<< std::endl;

編譯執行,結果如下

$ g++ u1402_3.cpp
$ ./a.out
0
1
2
$

相關教學影片

上一頁 14.1 - 條件編譯
回 C++ 速查手冊首頁
下一頁 14.3 - 引入標頭檔
回 C++ 教材
回程式語言教材首頁