一:背景
如果大家看過 CLR
源碼,會發現里面有很多 #define
宏定義,比如說 fusionhelpers.hpp
頭文件里。

如果你不熟悉 C ,看到這些 #define 應該會很暈的,這篇我們就來簡單聊聊 define 的玩法,其實說白了很簡單, #define
就是用一個標識符來包裝一段 常量
或者 函數體
,后續要復用這段邏輯時只需用此 標識符
即可。
這里要注意的是:替換發生在 編譯時
,如果不相信的話,可以從匯編上做驗證。
二:define 的簡單使用
1. 用 define 定義常量
這個是最常用的,上一段簡單的測試代碼:
#include?<iostream>#define?N?10int?main()
{printf("output:?s=%d",?N);
}output:?s=10
接下來我們探究下它的匯編代碼。
00531921??push????????0Ah??
00531923??push????????offset?string?"s=%d"?(0537B30h)??
00531928??call????????_printf?(05310D2h)??
0053192D??add?????????esp,8
從匯編中可以看出,并沒有出現 N
標識符的影子,而是直接將立即數 10
推送到棧上,大概就是下面這樣。
printf("s=%d",?10);
相信大家也看到了這個簡單替換,如果你還不信的話,我來演示一個 簡單替換
的坑,參考如下代碼:
#include?<iostream>#define?N?10+2int?main()
{float?f?=?N?/?2;printf("output:?s=%.1f",?f);
}output:?s=11.0
哈哈,你是不是天真的以為上面的輸出是 s=6
? 那就大錯特錯了,這個例子很好的反向證明了 確實是 替換
所致。
接下來我們來看下底層匯編
是咋樣的。
00f11925??movss???xmm0,?dword?ptr?[ConsoleApplication1!_real?(00f17b44)]
00f1192d??movss???dword?ptr?[ebp-8],?xmm00:000>?dp?00f17b44?L1
00f17b44??413000000:000>?.formats?41300000
Evaluate?expression:Hex:?????41300000Decimal:?1093664768Octal:???10114000000Binary:??01000001?00110000?00000000?00000000Chars:???A0..Time:????Sat?Aug?28?11:46:08?2004Float:???low?11?high?0Double:??5.40342e-315
從匯編代碼看,f 的值已經算好了存放在 00f17b44
地址上,值為 41300000
, 通過 .formats 命令可以看出 41300000
轉成 float 就是 11,很好的證明了它是在編譯時就已經處理好了。
有了這些基礎,改進方案就簡單了,用 ()
將 define 體包裝一下即可,參考如下:
#define?N?(10+2)
2. 用 define 定義函數
從 CLR 源碼上看,不僅僅可以定義 常量,還可以定義復雜的函數,接下來我們就演示一下。
#include?<iostream>#define?SUM(a,b)?a+bint?main()
{int?a?=?10;int?b?=?20;int?sum?=?SUM(a,?b);printf("output:?sum=%d",?sum);
}output:?sum=30
然后再看一下 int sum = SUM(a, b)
的匯編代碼。
00581925??mov?????????dword?ptr?[ebp-8],0Ah??
0058192C??mov?????????dword?ptr?[ebp-14h],14h??
00581933??mov?????????eax,dword?ptr?[ebp-8]??
00581936??add?????????eax,dword?ptr?[ebp-14h]
可以看到,那個 Sum
方法直接被 inline
了,高效哈,如果語句多的話,也可以在 ?#define 中用 ?{}
括起來,比如下面這樣。
#include?<iostream>#define?SUM(a,b)?{int?i=a;?int?j=b;?printf("output:?%d+%d=%d",i,j,(i+j));}int?main()
{int?a?=?10;int?b?=?20;SUM(a,b);
}output:?10+20=30
好了,今天就聊這么多,希望對大家有幫助!