ANSI C and Microsoft C++中常用的預定義宏)

來源:互聯網
上載者:User

__FILE__       源檔案的名稱  如XXX.cpp
__LINE__       代碼在源檔案中是第幾行 
__DATE__      源檔案完成日期如Eec 11 2012
__TIME__       源檔案完成時間如21:35:35
__TIMESTAMP__ 源檔案完成日期時間如Tue Dec 11 21:35:35 2012


如分配記憶體函數malloc()的一個版本就使用了上面的宏

#define   malloc(s)  _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)

另外可以在程式中使用__FILE__和__LINE__來確定是哪個檔案哪一行出錯:

       char *pszFileName = (char*)malloc(MAX_PATH * sizeof(char));

       if (pszFileName == NULL)

              printf("Error in %s %d\n",  __FILE__, __LINE__);

當然實際程式中大多用__FILE__和__LINE__快速定位錯誤後不會直接輸出,而是通過另一程式來將這些資訊以EMAIL形式反饋給開發人員。

 

對__FILE__可以方便的轉化成wchar_t類型,MSDN就有這個例子:

#define WIDEN2(x) L ## x

#define WIDEN(x) WIDEN2(x)

#define __WFILE__ WIDEN(__FILE__)

wchar_t *pwsz = __WFILE__;


宏中的#的功能是將其後面的宏參數進行字串化操作(Stringizing operator),簡單說就是在它引用的宏變數的左右各加上一個雙引號。

如定義好#define STRING(x) #x之後,下面二條語句就等價。

       char *pChar = "hello";

       char *pChar = STRING(hello);

還有一個#@是加單引號(Charizing Operator)

#define makechar(x)  #@x

       char ch = makechar(b);與char ch = 'b';等價。

 

但有小問題要注意,宏中遇到#或##時就不會再展開宏中嵌套的宏了。什麼意思了?比如使用char *pChar = STRING(__FILE__);雖然__FILE__本身也是一個宏,但編譯器不會展開它,所以pChar將指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源檔案名稱。因此要加一個中間轉換宏,先將__FILE__解析成"D:\XXX.cpp"字串。

定義如下所示二個宏:

#define _STRING(x) #x

#define STRING(x) _STRING(x)

再調用下面語句將輸出帶""的源檔案路徑

       char* pChar = STRING(__FILE__);

       printf("%s %s\n", pChar, __FILE__);

可以比較下STRING(__FILE__)與__FILE__的不同,前將帶雙引號,後一個沒有雙引號。

 

再講下##的功能,它可以拼接符號(Token-pasting operator)。

MSDN上有個例子:

#define paster( n ) printf( "token"#n" = %d\n", token##n )

int token9 = 100;

再調用  paster(9);宏展開後token##n直接合并變成了token9。整個語句變成了

printf( "token""9"" = %d", token9 );

在C語言中字串中的二個相連的雙引號會被自動忽略,於是上句等同於

printf("token9 = %d", token9);。

即輸出token9 = 100

 

 

有了上面的基礎後再來看樣本1

#define WIDEN2(x) L ## x

#define WIDEN(x) WIDEN2(x)

#define __WFILE__ WIDEN(__FILE__)

wchar_t *pwsz = __WFILE__;

第一個宏中的L是將ANSI字串轉化成unicode字串。如:wchar_t *pStr = L"hello";

再來看wchar_t *pwsz = __WFILE__;

__WFILE__被首先展開成WIDEN(__FILE__),再展開成WIDEN2("__FILE__表示的字串"),再拼接成 L"__FILE__表示的字串" 即L"D:\XXX.cpp" 從而得到unicode字串並取字串地址賦值給pwsz指標。

 

在VC中_T(),TEXT ()也是用的這種技術。

在tchar.h標頭檔中可以找到:

#define _T(x)       __T(x)

#define __T(x)      L ## x

在winnt.h標頭檔中可以找到

#define TEXT(quote) __TEXT(quote)   // r_winnt

#define __TEXT(quote) L##quote      // r_winnt

因此不難理解為什麼第三條語句會出錯error C2065: 'LszText' : undeclared identifier

       wprintf(TEXT("%s %s\n"), _T("hello"), TEXT("hello"));

       char szText[] = "hello";

       wprintf(TEXT("%s %s\n"), _T(szText), TEXT(szText));

而將"hello"定義成宏後就能正確運行。

#define SZTEXT "hello"

       wprintf(TEXT("%s %s\n"), _T(SZTEXT), TEXT(SZTEXT));

註:由於VC6.0預設是ANSI編碼,因此要先設定成unicode編碼,在project菜單中選擇Setting,再在C/C++標籤對話方塊中的Category中選擇Preprocessor。再地Preprocessor definitions編輯框中將_MBCS去掉,加上_UNICODE,UNICODE。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.