宏展開順序
宏展開順序大致可以歸結為:
第一步:首先用實參代替形參,將實參代入宏文本中
第二步:第一步代入實參后,分兩種情況:
1、實參之前遇到#或或之后遇到##,不管實參是不是宏,實參都將不再展開
2、如果實參前后沒有#或##,那就繼續展開實參,展開發現還是宏則繼續展開,直到展開到不能展開為止
第三步:最后繼續處理宏替換后的宏文本,如果仍包含宏,則繼續展開
參考:https://blog.csdn.net/FJDJFKDJFKDJFKD/article/details/83385708
宏展開的幾個注意事項:
1、每次宏展開的結果會被重復掃描,直到沒有任何可展開的宏為止。
2、每展開一個宏,都會記住這次展開,在這個宏展開的結果及其后續展開中,不再對相同的宏做展開。宏不能自引用:https://gcc.gnu.org/onlinedocs/cpp/Self-Referential-Macros.html
3、帶參數的宏,先對參數做展開,除非宏定義體中包含#或##
a) #表示將后續標識符轉換為字符串
b) ##表示將兩個標識符連接成一個標識符
c) 注意參數展開的結果中即使有逗號(,),也不視為參數的分隔符
如果宏定義中帶有參數,而代碼中出現同樣標識符時沒有參數,不視為宏。
參考:https://www.cnblogs.com/aquastone/p/c-macro-expansion.html
https://blog.csdn.net/KeLiaoo/article/details/109329661
編譯階段打印宏內容
首先介紹#pragma message 。 它能夠在編譯信息輸出窗口中輸出相應的信息,這對於源代碼信息的控制是非常重要的。其使用方法為:
#pragma message(“消息文本”)
假設我們希望判斷自己有沒有在源代碼的什么地方定義了_X86這個宏可以用下面的方法
#ifdef _X86
#pragma message(“_X86 macro activated!”)
#endif
下面的示例演示如何在編譯階段打印宏內容。
//兩個用於測試的宏
#define PI 3.1415926
#define MAX(a,b) (a)>(b) ? (a) :(b)
//首先定義兩個輔助宏
#define PRINT_MACRO_HELPER(x) #x
#define PRINT_MACRO(x) #x": "PRINT_MACRO_HELPER(x)
//編譯階段打印宏內容
#pragma message(PRINT_MACRO(PI))
#pragma message(PRINT_MACRO(PI2))
#pragma message(PRINT_MACRO(MAX(a,b)))
#pragma message(PRINT_MACRO(MAX(x,y)))
結果輸出
note: #pragma message: PI=3.1415926
//PRINT_MACRO中的兩個x都被替換為PI,PRINT_MACRO_HELPER中的#x替換為宏PI的內容
note: #pragma message: PI2=PI2
//PI2不存在的情況下PRINT_MACRO_HELPER將#x換做PI2
note: #pragma message: MAX(a,b)=(a)>(b) ? (a) :(b)
note: #pragma message: MAX(x,y)=(x)>(y) ? (x) :(y)
