C语言宏#和##
一、基本用途
#用于将宏定义中的参数转换为字符串。例:存在宏#define TO_STRING(x) #x则TO_STRING(hello)展开为"hello"
##用于拼接Token。
例:存在宏#define DECLARE_HANDLER(x) x##_handler则DECLARE_HANDLER(foo)展开为foo_handler
二、打印出展开后的宏
#define TO_STRING(x) #x#define MACRO_TO_STRING(macro) TO_STRING(macro)宏MACRO_TO_STRING将宏转换为字符串
例:
#define FOO_1(n) int a##n;
cout << MACRO_TO_STRING(FOO_1(1)) << endl;
将输出int a1;
三、宏参数替换中的#和##
Unicode下文件名的宏定义如下:#define WIDEN2(x) L##x#define WIDEN(x) WIDEN2(x)#define __WFILE__ WIDEN(__FILE__)
为什么不直接定义#define __WFILE__ WIDEN2(__FILE__)呢?这篇博文也是为此而生。
先来看看展开的结果:将MACRO_TO_STRING(__WFILE__)打印出来结果为L"D:\\TestMacro\\test.cpp"
如果定义#define __WFILE__ WIDEN2(__FILE__)
将MACRO_TO_STRING(__WFILE__)打印出来结果为L__LINE__
从结果可以看到__LINE__并没有展开。
四、宏参数替换标准
C99标准中6.10.3.16.10.3.1 Argument substitutionAfter the arguments for the invocation of a function-like macro have been identified,argument substitution takes place. A parameter in the replacement list, unless precededby a # or ## preprocessing token or followed by a ## preprocessing token (see below), isreplaced by the corresponding argument after all macros contained therein have beenexpanded.
当宏参数替换遇到#或##时,宏参数不会被宏定义替换。
#define WIDEN2(x) L##x#define WIDEN(x) WIDEN2(x)#define __WFILE__ WIDEN(__FILE__) 替换过程如下:__WFILE__WIDEN(__FILE__)WIDEN2("D:\\TestMacro\\test.cpp")L"D:\\TestMacro\\test.cpp"
而定义#define __WFILE__ WIDEN2(__FILE__)的替换过程如下:
__WFILE__WIDEN2(__FILE__)L__FILE__
WIDEN2宏定义替换参数遇到##,将该参数作为一般token处理,即使参数是个宏,也不替换该宏。
要展开的话,就需要增加一步中间操作,上例中的WIDEN(x)就是中间操作。 同理,上面的MACRO_TO_STRING打印宏定义的宏也是使用了TO_STRING作为了中间步骤。MACRO_TO_STRING(__WFILE__)TO_STRING(L"D:\\TestMacro\\test.cpp")"L"D:\\TestMacro\\test.cpp"" 参考资料:1.《C语言参考手册(原书第5版)》, Samuel P.Harbison / Guy L.Steele , 机械工业出版社2. C99标准 ISO/IEC 9899:1999 (E)