GCC扩展符(#,##)
2013-03-13 13:38
127 查看
先来说说这两个扩展符的各自用处吧,“#”是将宏字符串化(Stringification),“##”是将##左右两边的标签组合在一起(token pasting or token concatenation),下面从两个简单例子着手:
值得注意的是,##扩展符是用来连接两个标签,但是这两个标签之一不能为空!
但是使用这两个扩展符,有一个极容易出现错误的地方,那就是宏展开的问题,且看下面这个例子:
为什么str(foo)与xstr(foo)展开之后会出现完全不同的结果呢?此处就涉及到宏展开的规则问题:在宏预扫描((macro prescan)阶段,宏参数首先会被替换,替换之后,再经过下次的扫描完成最后宏的展开(macro expand),OK,说到此,似乎str(foo)在预扫描阶段应该会变成str(4),但是GCC在宏预处理阶段,特意加上了一条排外规则,那就是若宏参数被用于字符串化或者与其它标签连接,则不会被替代!结果也就可想而知了。下面是摘抄的一段预处理规则:
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens.
After substitution, the en-tire macrobody, including the substituted arguments, is scanned again for macros to be expanded.
【参考文献】
1. The C Preprocessor (For gcc version 4.7.2)
#define SSVAR(X,Y) const char X[]=#Y SSVAR(InternetGatewayDevice, InternetGatewayDevice.);上面这个例子实质是借用了#扩展符去实现名为InternetGatewayDevice的字符数组初始化,其等价代码(可以通过gcc –E展开获得)如下:
const char InternetGatewayDevice[]="InternetGatewayDevice.";下面这个例子比较常见,用于打开不同的路径。
#define DEV_FILE_NAME "/dev/test_kft" #define OPEN_FILE(fd, n) \ { \ fd = open(DEV_FILE_NAME ##n, 0); \ if (fd < 0) \ { \ printf("Open device error/n"); \ return 0; \ } \ } OPEN_FILE(fd1, 1); OPEN_FILE(fd2, 2);其展开的等价代码如下:
{ fd1 = open(DEV_FILE_NAME1, 0); if (fd1 < 0) { printf("Open device error/n"); return 0; } }; { fd2 = open(DEV_FILE_NAME2, 0); if (fd2 < 0) { printf("Open device error/n"); return 0; } };
值得注意的是,##扩展符是用来连接两个标签,但是这两个标签之一不能为空!
但是使用这两个扩展符,有一个极容易出现错误的地方,那就是宏展开的问题,且看下面这个例子:
#define xstr(s) str(s) #define str(s) #s #define foo 4 str(foo); //->”foo” xstr(foo); //->xstr(4)->str(4)->”4”
为什么str(foo)与xstr(foo)展开之后会出现完全不同的结果呢?此处就涉及到宏展开的规则问题:在宏预扫描((macro prescan)阶段,宏参数首先会被替换,替换之后,再经过下次的扫描完成最后宏的展开(macro expand),OK,说到此,似乎str(foo)在预扫描阶段应该会变成str(4),但是GCC在宏预处理阶段,特意加上了一条排外规则,那就是若宏参数被用于字符串化或者与其它标签连接,则不会被替代!结果也就可想而知了。下面是摘抄的一段预处理规则:
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens.
After substitution, the en-tire macrobody, including the substituted arguments, is scanned again for macros to be expanded.
【参考文献】
1. The C Preprocessor (For gcc version 4.7.2)
相关文章推荐
- GCC扩展 __attribute__ ((visibility("hidden")))
- GCC的__attribute__扩展功能
- 关于gcc扩展中的宏定义中用 "#" 和 "##"
- GCC扩展符(#,##)
- gcc对标准C/C++语言的扩展
- 内核中的gcc扩展
- GCC中switch的扩展
- gcc常用扩展
- 有关gcc的扩展__attribute__((unused))
- 利用gcc对C语言的语句内嵌表达式扩展定义lambda宏
- gcc的扩展__attribute__ ((cleanup(xxx))) 用于动态分配对象的自动释放
- 字节对齐详解-----(三)gcc 的字节对齐扩展
- GCC扩展
- GCC 对C语言的扩展(1)
- [gcc核心扩展]关于gcc中的typeof以及其他东东
- [转] GCC扩展(2)
- gcc中C语言扩展
- gcc扩展学习总结
- GCC 对C语言的扩展
- GCC下宏扩展后的++i