define

罕見

define 的概念

#define 是一個非常好用的小技巧,用途是「把程式碼中的某個字串替換成另一個字串」,中文名稱叫做「巨集」,你可以透過 #define 來把程式碼寫的更簡短!

define 的基本使用方式

#define 的使用方式很簡單,只要在程式碼中加入 #define 並指定一個名稱和一個值,之後在程式碼中使用這個名稱時,程式碼會自動替換成你所指定的值:

#define MAX 10
cout << MAX << endl; // 10

int a = MAX;
cout << a << endl; // 10

vector<int> v(MAX, 0);
cout << v.size() << endl; // 10

#define 的原理其實就是在編譯階段將程式碼中的 MAX 字串替換成 10,所以在編譯後的程式碼中是看不到 MAX 這個字串的。

#define 的行尾不需要加分號 ;,除非你想把分號也一起定義進去。

而且也可以用來替換更複雜一點的程式碼:

#define pii pair<int, int>
#define mp make_pair

pii p = mp(1, 2);
cout << p.first << " " << p.second << endl; // 1 2

當然也可以 #definemain 函式裡面,甚至是迴圈或者條件式裡面:

int main() {
    #define MAX 10
    cout << MAX << endl; // 10

    for (int i = 0; i < MAX; i++) {
        #define cool_variable i
        cout << cool_variable << " ";
    }
    cout << endl;
}

#define 最有意思的部分就是,它還可以拿來取代一些符號!

#include <bits/stdc++.h>
#define ouo <<
#define uwu cout
#define owo endl
#define awa int
#define qwq main()
#define u_u using
#define AWA namespace
#define OaO std

u_u AWA OaO;

awa qwq {
  uwu ouo "Hello World" ouo owo;
}

是不是很好玩呢?這樣就可以讓別人看不懂你的程式碼了!

define 一個函式

#define 也可以用來定義一個函式:

#define ADD(a, b) ((a) + (b))

int sum = ADD(1, 2);

cout << sum << endl; // 3

這樣就可以把 ADD 這個函式定義在程式碼中,而且不用寫 return,這樣的好處是可以讓程式碼更簡潔,但缺點是沒辦法像函式一樣做型態檢查,所以要小心使用。

多行 define

#define 也可以定義多行的程式碼,只要在每行的最後加上 \ 即可:

#define SWAP(x, y) \
    int tmp = x; \
    x = y; \
    y = tmp;

int a = 1, b = 2;

SWAP(a, b);

cout << a << " " << b << endl; // 2 1

好用的 define

尤其是在追求速度的競賽程式的文化中,已經發展出了許多經典的 #define 應用,例如:

#define rep(i, n) for (int i = 0; i < (n); i++)
#define for(i, a, b) for (int i = (a); i < (b); i++)
#define F first
#define S second
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define all(x) (x).begin(), (x).end()

上面這些 #define 都是為了讓程式碼更簡潔,例如 rep(i, n) 可以取代 for (int i = 0; i < n; i++)F 可以取代 firstpb 可以取代 push_back,等等。

而接下來介紹的這類 #define 則是有特定功能性的。

首先第一個就是用來避免 size_t 運算時變成負數造成錯誤,比如陣列為空的時候執行 v.size() - 1 就會變成一個很大的數字,這時候就可以用這個 #define 來避免這個問題:

#define sz(x) (int)(x).size()

接下來是用來加速程式輸出的 #define,原因 endl 這個語法其實不只有換行的功能,它還會同時刷新緩衝區,所以如果你非常大量的使用 endl 來換行,可能會造成程式執行速度變慢,這時候可以用這個 #define 來加速程式輸出:

#define endl '\n'

你有遇過因為數字太大而造成 overflow 的問題嗎?這時候可以用這個 #define 預先把 int 都定義成 long long 來避免這個問題,不過要注意有些函式傳值的時候要注意型態,且如果造成 TLE 或 MLE 可能要考慮改回 int

#define int long long

最後是用來避免浮點數精度不夠高的問題,這時候可以用這個 #definedouble 定義成 long double 來避免這個問題,當然這樣會增加程式的執行時間與記憶體使用量,所以要視情況使用:

#define double long double

小測驗

下列何者為正確的 #define 用法?