C语言宏#和##

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.1
6.10.3.1 Argument substitution
After the arguments
for the invocation of a function-like macro have been identified,
argument
substitution takes place. A parameter in the replacement list, unless
preceded
by a # or ## preprocessing token or followed by a ## preprocessing
token (see below), is
replaced by the corresponding argument after all macros
contained therein have been
expanded.

当宏参数替换遇到#或##时,宏参数不会被宏定义替换。

#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)

C语言宏#和##,布布扣,bubuko.com

时间: 2024-10-10 05:13:14

C语言宏#和##的相关文章

C语言宏应用-------#define STR(X) #X

#:会把参数转换为字符串 #define STR(x) #x #define MAX 100 STR(MAX) 会被扩展成"MAX" 这样就有一个缺陷,如果入参为宏,并不能打印出宏的值(比如上一个例子,只打印出了MAX,并没有打印出MAX的值) 可以将宏扩展下 #define _STR(x) #x #define STR(x) _STR(x) #define MAX 100 STR(MAX)会按照以下顺序替换 STR(100) _STR(100) "100" 最后输

常用的C语言宏定义

常用的C语言宏定义 1,防止一个头文件被重复包含      #ifndef COMDEF_H      #define COMDEF_H          //头文件内容      #endif       2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植.       typedef   unsigned char       boolean;      /* Boolean value type. */             typedef   uns

转载--c语言宏定义(1)

作者:独舞风 链接:c语言宏定义(1) 1.为什么要有宏定义? 代码中某个特定数值需要参与运算,而且该数值作用于多个地方,当需要对该数值进行修改时,希望只改动一个地方就能实现该数值的全部更新:即便某个数值只用到一次,当修改时也会面临搜索阅读大量代码.数值含义不明晰的问题:某些“操作块”封装成函数时,调用函数开销(保存上下文环境.参数调用.堆栈分配等)太大影响效率,不封装则需要多次输入相同的“操作块”内容,并且修改麻烦容易出现不一致的问题,这时就需要把“操作块”定义成宏,该方案本质是“空间换时间”

转载--c语言宏定义(2)

作者:独舞风 链接:c语言宏定义(2) 1.如何区分宏定义中的“宏名称”和“宏字符串”?对于带参数的宏又该注意什么? 在宏定义中,“宏名称”和“宏字符串”是通过“空格”来区分的,在宏的扩展中,空格会对扩展的结果造成很大的影响.编译器在处理时宏定义时,首先从“#define”后第一个空格开始读取字符串,直到遇见下一个空格为止,两个空格之间的字符串为“宏名称”,确定好“宏名称”之后,本行的所有其他字符串都为“宏字符串”.图示:#define + N个空格(1 < N) + 宏名称(中间没有空格) +

C语言宏的高级应用

原文:C语言宏的高级应用 关于#和##在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号.比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP "); } while(0) 那么实际使用中会出现下面所示的替换过程: WARN_IF (divider == 0);被替换为

C语言宏预处理帮助文档

GCC4.10预处理器帮助文档 The C Preprocessor Transformations Made Globally Most C preprocessor features are inactive unless you give specific commands to request their use. (Preprocessor commands are lines starting with `#'; see section Preprocessor Commands).

C 语言宏定义

C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; PRINT_STR(str); 结果如下:abcd2.现在我期望打印出,str=abcd, 容易想到的解决办法是: #define PRINT_STR(s) printf("s" "=" "%s",s.c_str()) 打印出来的结果是 s=abcd

将C语言宏定义数值转换成字符串!

将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 阅读数:10185 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/happen23/article/details/50602667 适用场景举例 流媒体处理系统中,采样率是个很重要的参数,很多地方都要用,如果用来分配内存,则 #define S

C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)

C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量 通过替换后在其左右各加上一个双引号.比如下面代码中的宏: #define WARN_IF(EXP) do{ if (EXP) fprintf(stderr, "Warning: " #EXP &quo