二:C语言宏定义的小知识
此处的tip是为了收集宏定义常见坑,后续还会更新(如果更新会有相应的链接出现,如果发现我有什么纰漏,—— + ——希望评论区留言)
——)
(1)基础知识
1宏体换行需要在行末加上反斜杠\
#define NUMBERS 1, \
2, \
3
显然最后一行就不用了【苦笑】
2宏函数,
宏名后面加个括号就是宏函数(与普通函数区别不大,使用目的是为了降低开销,处理速度,就是要多加括号,防止替换后出现歧义)(还有就是记得加上do{ }while(0))
那既然同为函数那么传递参数时就有下面三种形式:
1》直接传递x
2》传递#x 那么在宏体扩展的时候,宏参数会被扩展成字符串的形式 相当于换用“x”替换(字符串化)
3》传递##x 那么在宏体扩展的时候,宏参数会被直接替换到标示符中
#define COMMAND(NAME) { #NAME, NAME ## _command }
COMMAND(quit);
//宏扩展结果:
{"quit",quit_command},
(2)坑
1语法问题
由于是纯文本替换,C预处理器不对宏体做任何语法检查(像缺个括号、少个分号,那就只能自求多福了)(千万不要吝啬你的括号)
2优先级问题 #
宏参数也是纯文本替换(——==——),千万不要替换错了
—
#define MULTIPLY(x, y) x * y
MULTIPLY(1+2, 3);
宏扩展结果:
1+2*3;//显然这不是你想表达的意思
//修改为#define MULTIPLY(x, y) (x) * (y)
宏扩展结果:
(1+2)*(3);//完美
3 do { }while(0)用法
文章一中有具体解释
4最好不要再宏参数中使用函数调用
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
next = min (x + y, foo (z));
宏展开结果
next = ((x + y) < (foo (z)) ? (x + y) : (foo (z)));
//foo(z)被重复调用了两次,做了重复计算。
5对自身的递归引用(你想多了,它只展开一次)
#define foo (4 + foo)
宏展开结果:
(4 + (4 + foo))
//交叉引用也是一样的(只展开一次)
#define x (4 + y)#define y (2 * x)
(4 + y) -> (4 + (2 * x))
(2 * x) -> (2 * (4 + y))
//这样写太晦涩(不建议使用)
6宏参数的预处理机制
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
1》AFTERX(BUFSIZE)会被展开成X_BUFSIZE。因为宏体中含有##,宏参数直接代入宏体。
2》XAFTERX(BUFSIZE)会被展开成X_1024。因为XAFTERX(x)的宏体是AFTERX(x),并没有#或##,所以BUFSIZE在代入前会被完全展开成1024,然后才代入宏体,变成X_1024。