深入理解“宏”

宏的作用是将一个标识符指定为其他替换列表的预处理记号。可以定义两种形式的宏:
1、对象式宏
2、函数式宏

宏使用注意事项:

1、宏不允许重复定义(排除替换列表完全等价的情况)。
2、可以使用#undef指令取消先前定义的宏。
3、宏不支持递归。
4、宏名必须全为大写。
5、宏的替换列表需要用小括号。

对象式宏
对象式宏定义使用如下:
在这里插入图片描述
分析:

例程3中data 宏名为小写不符合规范

例程4中TEST 替换列表中没有使用小括号

宏函数式宏

函数式宏定义可以有参数,参数位于宏名之后的一对小括号中。函数式宏使用注意事项:

1、每个宏参数的作用域为从它出现位置开始,到当前宏结尾。
2、宏名和左括号“(”之间不能有空白。

实例如下:
在这里插入图片描述
分析:

例程2中SQUARE这个宏违反替换列表需要用小括号这条规则,如SQUARE(1+2)的结果式1+2*1+2 为5,并非想要的求平方的结果!

函数式宏和函数的最大区别是:

函数式宏的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,省去了函数的调用,返回,效率比函数高(产生的代码文件较大)。

“#”和“##”在宏中使用
“#”记号串化

记号串化可以将函数式宏中的参数转换为字符串。替换列表中的参数紧跟记号串化“#”后,实例如下:
在这里插入图片描述
分析:buff[] 内容为 “liyinuo2017 liwei”

“##”记号黏结

记号黏结的作用是将几个预处理记号合并成一个。

实例1:
在这里插入图片描述
分析: 等效为char liwei;

实例2:
在这里插入图片描述
分析:SYSCALL_DEFINE(my_call); 等效为 long sys_my_call(void);

展现一个复杂的例子:
在这里插入图片描述
分析:_syscall0 为linux内核添加系统调用的一个宏,感兴趣的朋友可以查找_syscall0相关资料。

创作不易希望朋友们点赞,转发,关注。希望获取源码的朋友们在评论区里留言。
作者:李巍
Github:liyinuoman2017

おすすめ

転載: blog.csdn.net/li_man_man_man/article/details/121527938