原文地址::http://blog.csdn.net/breakerzy/article/details/6908820
相关网帖
1.VC预处理指令与宏定义的妙用----http://blog.csdn.net/ningyaliuhebei/article/details/7545403
作者:Breaker Zhao
转载请注明作者和原文链接
VC 2005 中的宏 (#define) 与预处理 (#if/#ifdef/#pragma) 的使用方法总结。
关键字:宏, 预定义宏, 预处理, 预编译头, VC, #pragma, 编译选项, 程序区段
VC 中的宏使用方法参考 MSDN: Macros (C/C++)
C/C++ 预定义宏^
__LINE__: 当前源文件的行号,整数
__FILE__: 当前源文件名,char 字符串,使用 /FC 选项产生全路径
__DATE__: 当前编译日期,char 字符串,格式 Aug 28 2011
__TIME__: 当前编译时间,char 字符串,格式 06:43:59
__STDC__: 整数 1,表示兼容 ANSI/ISO C 标准,配合 #if 使用
__TIMESTAMP__: 最后一次修改当前文件的时间戳,char 字符串,格式 Sun Aug 28 06:43:57 2011
__cplusplus: 以 C++ 方式而非 C 语言方式编译时定义,VC 2005 中定义为 199711L,配合 #ifdef 使用
例子:C/C++ 预定义宏的取值^
- // MacroTest.h
- void PrintSourceInfo()
- {
- const _TCHAR* pszstdc;
- const _TCHAR* pszcpp;
- #if __STDC__
- pszstdc = _T("YES");
- #else
- pszstdc = _T("NO");
- #endif
- #ifdef __cplusplus
- pszcpp = _T("YES");
- #else
- pszcpp = _T("NO");
- #endif
- _tprintf(_T("File: %s, Line: %d, Date: %s, Time: %s, Timestamp: %s, ANSI/ISO C: %s, C++: %s\n"),
- _T(__FILE__), __LINE__, _T(__DATE__), _T(__TIME__), _T(__TIMESTAMP__), pszstdc, pszcpp);
- }
- // 宏化的 PrintSourceInfo()
- #define PRINT_SOURCE_INFO() \
- _tprintf(_T("File: %s, Line: %d, Date: %s, Time: %s, Timestamp: %s\n"), \
- _T(__FILE__), __LINE__, _T(__DATE__), _T(__TIME__), _T(__TIMESTAMP__));
MacroTest.h 中定义函数 PrintSourceInfo() 和 PRINT_SOURCE_INFO(),在 MacroTest.cpp include=> MacroTest.h,并调用它们
输出结果:
(1). 使用函数 PrintSourceInfo(),无论 Debug/Release 方式编译,无论是否 inline 化 PrintSourceInfo(),输出结果相同,均是 MacroTest.h 的信息:
File: d:\source\macrotest\macrotest.h, Line: 64, Date: Aug 28 2011, Time: 06:43:59, Timestamp: Sun Aug 28 06:43:57 2011, ANSI/ISO C: NO, C++: YES
(2). 使用宏 PRINT_SOURCE_INFO(),Debug/Release 方式编译输出结果大致相同,均是 MacroTest.cpp 的信息,只是 Debug 输出的 __FILE__ 是全路径,而 Release 输出的是相对路径:
File: d:\source\macrotest\macrotest.cpp, Line: 14, Date: Aug 28 2011, Time: 07:42:30, Timestamp: Sun Aug 28 07:38:25 2011
说明:
(1). __FILE__、__DATE__、__TIME__ 是 char 字符串,而不是 wchar_t 宽字符字符串,需配合 _T()、_t 系列函数使用
(2). 如果在函数 PrintSourceInfo() 中使用宏,则 __FILE__、__LINE__、__TIME__ 等表示的是 PrintSourceInfo() 所在文件,即例 1 中的 MacroTest.h 的信息;如果在宏 PRINT_SOURCE_INFO() 中使用宏,因为宏 PRINT_SOURCE_INFO() 嵌套展开的缘故,__FILE__ 等表示的是 PRINT_SOURCE_INFO() 展开所在文件,即 MacroTest.cpp 的信息
(3). 无论使用 PrintSourceInfo() 还是 PRINT_SOURCE_INFO(),__LINE__ 总是文件 .h/.cpp 的固有行号,而非 [MacroTest.cpp include=> MacroTest.h] 预处理展开后的行号
(4). 在 VC 2005 中,上述编译方式下没有定义 __STDC__,要使 __STDC__ = 1,应同时满足以下条件:
- (a). 以 C 方式编译
- (b). 使用编译选项 /Za,表示禁止 Microsoft C/C++ 语言扩展,从而兼容 ANSI C/C++
C/C++ 预定义宏用途:诊断与调试输出^
参考 VC CRT 和 MFC 的代码,注意:需要在宏中使用 __FILE__、__LINE__,原因见上面“说明 (2)”
CRT 的诊断与调试输出:assert, _ASSERT/_ASSERTE, _RPTn/_RPTFn/_RPTWn/_RPTFWn^
CRT 的诊断宏 assert()、_ASSERT()/_ASSERTE()
- // assert.h
- _CRTIMP void __cdecl _wassert(__in_z const wchar_t * _Message, __in_z const wchar_t *_File, __in unsigned _Line);
- #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
- // crtdbg.h
- #define _ASSERT_EXPR(expr, msg) \
- (void) ((!!(expr)) || \
- (1 != _CrtDbgReportW(_CRT_ASSERT, _CRT_WIDE(__FILE__), __LINE__, NULL, msg)) || \
- (_CrtDbgBreak(), 0))
- #ifndef _ASSERT
- #define _ASSERT(expr) _ASSERT_EXPR((expr), NULL)
- #endif
- #ifndef _ASSERTE
- #define _ASSERTE(expr) _ASSERT_EXPR((expr), _CRT_WIDE(#expr))
- #endif
CRT 的调试输出宏 _RPTn()/_RPTFn(),n: 0 ~ 5
_RPTWn()/_RPTFWn() 是宽字符版
- // crtdbg.h
- #define _RPT_BASE(args) \
- (void) ((1 != _CrtDbgReport args) || \
- (_CrtDbgBreak(), 0))
- #define _RPTF0(rptno, msg) \
- _RPT_BASE((rptno, __FILE__, __LINE__, NULL, "%s", msg))
MFC 的诊断与调试输出:ASSERT/VERIFY, ASSERT_VALID, TRACE/TRACEn^
MFC 的诊断宏 ASSERT()/VERIFY()、ASSERT_VALID()
- // afx.h
- #define ASSERT(f) DEBUG_ONLY((void) ((f) || !::AfxAssertFailedLine(THIS_FILE, __LINE__) || (AfxDebugBreak(), 0)))
- #define ASSERT_VALID(pOb) DEBUG_ONLY((::AfxAssertValidObject(pOb, THIS_FILE, __LINE__)))
MFC 的调试输出宏 TRACE()/TRACEn(),n: 0 ~ 3