最近被C语言中#和##的宏定义作用弄的有些头晕,花了点时间整理收集了一些内容,希望对大伙有点帮助吧,不多说,来干货。
宏中“#”的用法
1.可以把宏参数变为一个字符串
在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组
e.p.
#include
#define STR(s) #s
int main()
{
char* s = STR(patrickpan);
printf("%s\n", p);
return 0;
}
2.合并匿名变量名
#define ___ANONYMOUS1(type, var, line) type var##line
#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示该行行号;
第一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
第二层: --> ___ANONYMOUS1(static int, _anonymous, 70);
第三层: --> static int _anonymous70;
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开。
3.填充结构
#define FILL(a) {a, #a}
enum IDD{OPEN, CLOSE};
typedef struct MSG{
IDD id;
const char * msg;
}MSG;
MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
相当于:
MSG _msg[] = {{OPEN, "OPEN"},
{CLOSE, "CLOSE"}};
4.分号吞食问题
有如下宏定义:
#define SKIP_SPACES(p, limit) \
{ char *lim = (limit); \
while (p < lim) { \
if (*p++ != ' ') { \
p--; break; }}}
假设有如下一段代码:
if (*p != 0)
SKIP_SPACES (p, lim);
else
...
这时如果编译的话,GCC将会报:error: 'else' without a previous 'if'。看似是一个函数的宏被展开为一段代码块,加上分号这个if逻辑块就结束了,所以比那一切发现这个else没有对于的if
这个问题一般用do{}while(0)的形式来解决;
#define SKIP_SPACES(p, limit) \
do { char *lim = (limit); \
while (p < lim) { \
if (*p++ != ' ') { \
p--; break; }}} \
while (0)
展开后就成了
if (*p != 0)
do{...}while(0)
else
...
这样就可以消除分号吞噬问题。
宏中“##”的用法
1.##可以把两个宏参数粘合在一起
e.p.
#include
#include
#define MERGE(a,b) a##b
#define CONS(a,b) int(a##e##b)
int main()
{
int t = MERGE(2,3);
printf("t=%d\n", t);
char* ab = "pantianxing";
char* p = MERGE(a,b);
printf("output:%s\n", p);
printf("cons=%d\n",CONS(2,3));
return 0;
}
输出如下:
t=23
ouput:pantianxing
cons=2000 // 2e3=2000
引用参考的文章如下:
http://idas643.blog.163.com/blog/static/1671048382015461049289/
http://www.voidcn.com/blog/earbao/article/p-6254938.html
http://cvrs.whu.edu.cn/blogs/?p=231
阅读(859) | 评论(0) | 转发(0) |