C的巨集使用技巧1
Posted by: kevinlin on: 三月 28, 2006
其實在寫遊戲時巨集還蠻需要的因為比較方便,很多C++的書都說用inline來取代C語言底層的巨集,不過這種說法都太片面了,沒有考慮到巨集的一些獨特的功能。就本質上來說,巨集只是對編譯器的前置處理器做一些指示,做一些比較smart的text的替換的工作。所以他最嚴重的問題是出在這邊,他不會檢查類型或者其他的安全性的檢查,所以開發人員會增加不少麻煩。但是只要遵守著一條原則就可以避免,那就是不要用巨集來建立有函式功能的行為或著常數。
下面介紹一下幾個使用巨集的技巧:
1. 把列舉值轉換成字串
#define CaseEnum(a) case(a): LogMsgToFile(#a, id, time)
switch( msg_passed_in )
{
CaseEnum( MSG_YouWereHit );
ReactToHit();
break;
CaseEnum( MSG_GameReset );
ResetLogic();
break;
}
上面這個經過編譯器的處理後 會變成下面這樣
switch( msg_passed_in )
{
CaseEnum( MSG_YouWereHit );
LogMsgToFile(“MSG_YouWereHit “, id, time);
ReactToHit();
break;
CaseEnum( MSG_GameReset );
LogMsgToFile(“MSG_GameReset”, id, time);
ResetLogic();
break;
}
利用這個方式,可以很輕鬆並且可靠的把列舉的值轉換成有意義的輸出,例如字串想要輸出到LOG檔案或顯示到螢幕上。如果不用這樣的方法,就需要自己做一個的對照表。不過通常這個對照表的維護性很差(應該沒人會去記得要維護:P),而且不太可靠。另外一個方法是全部都使用字串,而不用列舉,但是在遊戲裡面理論上來說應該還不適合用字串的比較。所以這個方法算是一個快速又可靠的安全解決方案了。
另一個使用這的用法,是可以把一組列舉放在一個標頭檔裡,然後在使用的時候把他放在不同的列表裡,好讓我們同時取得列舉跟字串。
// data.h
DATA(MSG_YouWereHit)
DATA(MSG_GameReset)
DATA(MSG_HealthRestored)
// data.cpp
#define DATA(x) x,
enum GameMessages
{
#include “data.h”
};
#undef DATA
#define DATA(x) #x, // 使列舉值轉換成字串
static const char* GameMessageNames[] =
{
#include “data.h”
};
#undef DATA
七月 30, 2008 於 10:17 午後
#define CaseEnum(id) case id: LogMsgToFile(#a, id, time)
switch( msg_passed_in )
{
case MSG_YouWereHit:
LogMsgToFile(”MSG_YouWereHit “, id, time);
ReactToHit();
break;
case MSG_GameReset:
LogMsgToFile(”MSG_GameReset”, id, time);
ResetLogic();
break;
}