C语言#define用法总结
发布时间:2018-06-06 16:27:54
发布时间:2018-06-06 16:27:54
C语言#define用法总结
黄海涛,2012-3-3
如果你还在为使用#define而迷茫,那请阅读这篇文章;
如果读完之后你还在迷茫,那请哪天心情好了,再回来读一遍。:)
欢迎跟着我的思路走……
一、 概述
1、 宏定义
在C语言中,以#开头的为预处理命令。
定义形式:
#define name replacement text
2、 本质
其本质是:使用宏定义中的字符串替换(Substitution)宏名。
这只是一种简单的代换,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。
3、 替换时机
预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。由预处理程序负责完成。在源程序被编译之前,宏替换已经完成,其流程如下:
源程序 预处理程序 预处理后的源程序 编译器
4、 作用域
其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用# undef命令。
5、 优缺点
▲优点:宏定义使用得当,可以防止出错,提高可移植性,可读性等等;减少函数调用的开销。
▲缺点:可能存在参数副作用;展开后可能比函数调用开销更大。
※规则一:保证在宏替换之后不会发生错误。
二、 无参宏定义
1、 定义的一般形式
#define identifier token-sequence
#define 标识符 字符串
2、 简单常量
代替有实际意义的常量,如:
● 约束1:宏名通常采用易读大写字母表示。
● 约束2:宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换。
● 约束3:宏名在源程序中若用引号引起来,则预处理程序不对其作宏替换。如:
3、 字符串为表达式
※规则二:无参宏定义中字符串为表达式(即含有运算符),必须加小括号()。
可见,有括号与无括号差别很大,请小心加括号,保证展开后是你所期望的。参考规则一。
4、 嵌套使用
5、 指明数据类型限制
6、实例
三、 带参宏定义
对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。
1、 带参宏定义的一般形式为:
#define identifier(identifier-list) token-sequence
#define 宏名(形参表) 字符串
在字符串中含有各个形参,形参是标识符。
带参宏调用的一般形式为:
宏名(实参表);
● 约束4:带参宏定义中,宏名和‘(’之间不能有空格出现。
※规则三:带参宏定义中,字符串是表达式(不是语句),要求严格加小括号,即对每个参数、每一层运算、整个字符串都要求加小括号。
2、 简单用法:
我们经常讨论的一个宏定义:给定两个整数,求其中较大者。有很多人无法将它完全写正确。
看到了吧,编写一条正确的宏定义不容易,如果你不按规则办事,总有一天你会为调试它而费上九牛二虎之力!(而且你是没有办法在宏定义处设置断点的,因为在编译之前,宏展开已完成。)
3、 占用多行的写法
可以用\换行续写
4、 字符串为语句
※ 规则四:字符串为语句,要求加大括号。
如下调用:
加大括号后的问题:
如下调用:
如果你非得用宏定义来写的话,那就得如下处理:
四、 特殊用法
1、 防止头文件被重复包含
2、 表示数据类型(更多的时候是使用typedef)
因为宏并不是类型定义,只是简单替换而已。
3、 连接
4、 添加单引号
5、 添加双引号
以上三个特殊运算符(##, #@与#),会影响替换过程。
1) 它们后面紧接形式参数的话,将会进行相应的操作(连接或加引号)。
2) 当宏展开后,再次扫描并再次遇到此类标识符时不再执行替换,而是保持不变。
3) 当宏展开后,得到的最终结果以#开头,不会认为是预处理命令。
五、 宏定义中的问题
1、 参数可能有副作用
解决办法:
1) 确保参数没有副作用;
2) 将宏改写为函数,进行函数调用;
3) 直接写运算代码。
2、 导致效率低下
解决办法:
1) 直接写运算代码;
2) 将宏改写为函数,进行函数调用。
有了对基本用法的掌握,分析相对复杂一些的情况应该不在话下了。另外,文中肯定存在很多不足之处,恳请阅读者批评指正,相互交流,学习提高。
六、 参考资料
1、《C程序设计》(第三版):谭浩强著,清华大学出版社2005.07
2、《C程序设计语言(The C Programming Language)》(第2版中英文版):(美)Brian W.Kernighan,Dennis M.Ritchie著,徐宝文 李志译,机械工业出版社2004 年1月
3、《C专家编程(Expert C Programming)》(中英文版):(美)林登(LinDen,P.V.D)著,徐波译,人民邮电出版社2002.12
4、《C陷阱与缺陷(C Traps And Pitfalls)》(中英文版):(美)Andrew Koenig,高巍译,人民邮电出版社2003
5、《C语言深度解剖》陈正冲著,北京航空航天大学出版社2010
6、《想成为嵌入式程序员应知道的0x10个基本问题.doc》作者:Jones Nigel