C/C++ define 用法與範例

本篇 ShengYu 介紹 C/C++ define 用法與範例。

以下 C/C++ define 用法介紹將分為這幾部份,

  • C/C++ define 基本用法
  • C/C++ define 單行巨集的範例
  • C/C++ define 多行巨集的範例
  • C/C++ 取消巨集
  • C/C++ define 來簡化函式
  • C/C++ 預定義巨集

那我們開始吧!

C/C++ define 基本用法

以下為 C/C++ define 語法,define 前面加上 #,define 最後面不需加上;分號,define 的順序跟 typedef 是不一樣的,容易搞混,需要特別注意一下,

1
#define <NEW_NAME> <EXIST_NAME>

例如,define PI 為 3.1415,define HELLO_WORLD_STR 為 “Hello World”,

1
2
#define PI 3.1415
#define HELLO_WORLD_STR "Hello World"

C/C++ define 單行巨集的範例

以下示範 C/C++ define 單行巨集,

cpp-define.cpp
1
2
3
4
5
6
7
8
9
10
11
// g++ cpp-define.cpp -o a.out
#include <stdio.h>

#define PI 3.1415
#define HELLO_WORLD_STR "Hello World"

int main() {
printf("PI: %f\n", PI);
printf("%s\n", HELLO_WORLD_STR);
return 0;
}

輸出如下,

1
2
PI: 3.141500
Hello World

C/C++ define 多行巨集的範例

以下示範 C/C++ define 多行巨集,多行可以用反斜線換行,

1
2
3
4
#define MACRO(arg1, arg2) do { \
stmt1; \
stmt2; \
} while(0)

例如:兩整數交換的 SWAP 可以這樣寫,

1
2
3
4
#define SWAP(x, y) \
int tmp = x; \
x = y; \
y = tmp;

實際的範例如下,

cpp-define2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// g++ cpp-define2.cpp -o a.out
#include <stdio.h>

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

int main() {
int a = 3;
int b = 5;
printf("a: %d, b: %d\n", a, b);
SWAP(a, b);
printf("a: %d, b: %d\n", a, b);
return 0;
}

輸出如下,

1
2
a: 3, b: 5
a: 5, b: 3

C/C++ 取消巨集

C/C++ 取消巨集語法如下,使用 #undef 後面接上巨集名稱,

1
#undef <macro name>

undef 取消巨集範例如下,

cpp-define3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// g++ cpp-define3.cpp -o a.out
#include <stdio.h>

#define DEBUG
#undef DEBUG

int main() {
#ifdef DEBUG
printf("DEBUG\n");
#else
printf("NO DEBUG\n");
#endif
return 0;
}

輸出如下,

1
NO DEBUG

C/C++ define 來簡化函式

define 巨集可以用來簡化函式,例如我們 define 一個 DEBUG_PRINT 巨集用來將資料輸出到錯誤輸出上,

1
2
3
4
5
6
#define DEBUG_PRINT(fmt, ...) do { fprintf(stderr, fmt, __VA_ARGS__); } while (0)

// 使用範例
DEBUG_PRINT("error message");
// 使用範例
DEBUG_PRINT("error code: %d", errorcode);

或 Android 常見的 log 輸出函式,

1
2
3
4
5
6
7
8
#include <android/log.h>

#define TAG "MYDEBUG"
#ifdef DEBUG
#define ALOGD(...) do { __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__); } while (0)
#else
#define ALOGD(...) do {} while (0)
#endif

C/C++ 常用巨集

1
2
3
4
5
#define MIN(a, b) (a < b ? a : b)
#define MAX(a, b) (a > b ? a : b)
#define ADD(x, y) (x + y)
#define SUB(x, y) (x - y)
#define SWAP(x, y) int tmp = x; x = y; y = tmp;

寫 macro 時有時會遇到一些陷阱,例如乘法 MULT 這個巨集如下,

1
#define MULT(x, y) x * y

上面這種寫法乍看沒什麼問題,實際上會因為 MULT(1+1,2+2); 這樣使用後被展開成 1+1*2+2 = 5 而造成結果不對。
所以會改成下這樣寫法,加上括號,

1
#define MULT(x, y) (x) * (y)

這樣寫的話展開成 (1+1)*(2+2) = 2*4 = 8 結果就正確了。
最保險的方式是把每個變數都用括號把它包起來,這也就是為什麼常看到別人寫的巨集都多了好多括號的原因。

C/C++ 預定義巨集

以下是 C/C++ 常用的預定義巨集,

1
2
3
4
5
__FILE__,原始碼檔案路徑  
__LINE__,原始碼行數
__FUNCTION__,函式名稱
__func__,函式名稱
__VA_ARGS__,可變引數的巨集

以上就是 C/C++ define 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其他參考
c preprocessor - #define macro for debug printing in C? - Stack Overflow
https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c
(Android系统)android log机制浅析_威猛の小脑斧的博客-CSDN博客___android_log_write
https://blog.csdn.net/lele_cheny/article/details/34858503
用macro的技巧 | 技術筆記
http://twmht.github.io/blog/posts/cc/macro.html

其它相關文章推薦
如果你想學習 C/C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ typedef 用法與範例
C/C++ sizeof 用法與範例