例: 常見的 ## (連接), #@ (字元化), # (字串化)
1. x ## y :表示x連接y, 注意x與y需同一型態
2. #@ x :據說可以字元化, 但這是不常用的語法, 而且我編譯會出現error: ‘#’ is not followed by a macro parameter
3. # x :表示將x字串化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#define beConn(x, y) x ## y //#define ToChar(x) #@ x #define beStr(x) # x int main(void) { int num = beConn(12, 34); printf("beConn(12, 34) : %d \n", num); // char c = ToChar(1); // printf("beChar(1) : %c \n", c); printf("beStr(I am string) : %s \n", beStr(I am string)); return 0; } |
輸出:
beConn(12, 34) : 1234
beStr(I am string) : I am string
例: 透過 #define 可以變成 function
定義更美觀易讀的語法, ” \” 表示視為同一行
1 2 3 4 5 6 7 8 9 |
#define ATK_CHK(list, cb, skb, dir) \ { \ int atk; \ \ for (atk = 0 ; list[dir][atk] != EMPTY_VALUE ; atk++) { \ if(cb[list[dir][atk]] && cb[list[dir][atk]](skb, (struct iphdr *)skb->nh.iph) == IS_ATTACK) \ return AEGIS_BLOCK; \ } \ } |
例: 透過 #define 與內嵌X()變化, 做出enum與之字串化
延伸閱讀:
C語言巨集macro: 將enum的integer變數 印出變成string
1. 假設這段程式碼可用於pwr_state.h檔案 當作宣告 stringify_PWR_state_t()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#pragma once #define PWR_STATES \ X(PWR_STATE_ENABLED, 0) \ X(PWR_STATE_DISABLED_REBOOT_REQUIRED, 1) \ X(PWR_STATE_DISABLED_MANUAL_ENABLE, 2) \ X(PWR_STATE_DISABLED, 3) \ X(PWR_STATE_PSW_NOT_AVAILABLE, 4) \ X(PWR_STATE_UNKNOWN, -1) #define X(x_state, x_value) x_state = x_value, typedef enum { PWR_STATES } pwr_state_t; #undef X const char* stringify_pwr_state_t(pwr_state_t state); |
2. 然後更改一下x()的定義, 假設在pwr_state.c檔案
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <pwr_state.h> #define X(x_state, x_value) case x_state: return # x_state; const char* stringify_pwr_state_t(pwr_state_t state) { switch (state) { PWR_STATES default: return "Unknown state."; }; } #undef X |