C++中如何更好使用宏定义#define

首先我们需要明确一点,在c++中不提倡使用宏。我们可以使用const代替,来定义一般的常量。对于一些函数,可以考虑inline关键字,可以达到同样的高效率。

1.为什么c++中不提倡使用宏呢?

       这主要是由于宏背后所潜藏的安全机制以及误用频繁造成的。

       对于宏,我们应明白其实质就是“替换”,编译器在编译阶段就会进行宏替换,使用你所定义的常量(函数)替换所有出现该定义位置,其替换过程说白了,仅仅是字符替换而已,因而会因此发生很多误用,最常见的就是所谓的“边际效应”。

例如:

#define N 100
#define M 200 + N
       当你在程序中使用 M*N 时,原本想要的应该是100 * (200+ N ),而实际上,编译器却给你变成了 100 * 200 + N,这就是所谓的边际效应,说白了,就是替换出现了错误。(我在后面会讲述这一问题的注意事项)

       形成良好地编写习惯是一个优秀程序员的基本素质。记住一句话:编程是一门艺术,态度决定高度,细节决定成败!

C++中如何更好使用宏定义define - 小影不爱睡 - 影 的博客

 

       而且,宏定义,缺乏类型定义,因而也就自然没有类型安全性检测。这和const形成鲜明的对比,const定义的常量编译器可以对其进行数据静态类型安全检查(比如,int型,double型等),而#define宏定义的常量却只是进行简单的字符替换,你不要指望编译告诉你,定义的数值过大等等。

       还有,宏定义无法进行调试。由于在编译前的预编译阶段已经进行了宏替换,所以在更后面的调试等等环节,你根本不用指望调试中出现你所定义的原型,有时候,这样就造成很多困扰。再此,我建议也可以阅读以下《effective c++》的相关章节,链接如下:

http://www.kuqin.com/effectivec2e/ch00b.htm

C++中如何更好使用宏定义define - 小影不爱睡 - 影 的博客

 

2.为什么c++中又允许宏定义?

       首先,肯定是为了与c兼容。

       其次,虽然宏定义有种种弊端,但这些实际上是c所带来的避短而已,我们通过刻意训练完全可以避免,而且,说实话,宏定义确实带来了某些好处,后面的文章里会讲的很清楚。

       再其次,有时候,宏定义是你唯一的,或者最便捷的选择(在保证安全性前提下)。比如,在MFC下常见的声明与注销(#undef),条件编译(我更喜欢把条件编译称为一个开关,具体我会在后面阐述)等。

3.c++中宏定义的使用方法进阶

       阅读本文章的你,我会认为你已经掌握了基本的宏定义使用方法,包括:宏常量定义、无参数宏函数定义、有参数宏函数定义。本文仅就其衍生以及进行阐述。推荐先阅读下面链接:

http://www.cppblog.com/kevinlynx/archive/2008/03/19/44828.html

http://blog.163.com/lorry_717/blog/static/170530942201122211482485/

补充部分:

       有参数宏函数定义中,"\","#","#@"和"##"说明:用#define 定义时 , 斜杠("\")是用来续行的,用于多行宏定义函数书写。"#"用来把参数转换成字符串,是给参数加上双引号"#@"是给参数加上单引号。"##"则用来连接前后两个参数,把它们变成一个字符串。我很有必要提醒一下你,这几种都是用于宏函数定义的,因此如果误用于常量定义,就会报“无效字符 : 可能是宏扩展的结果”等错误。

       typedef与#define都可以用于定义,作用都类似于起别名。为了防止潜在的错误,我建议,在定义关键字、类型时,使用typedef,而定义常量、函数等用define。可以参考下面链接:

http://blog.163.com/xiangzaihui@126/blog/static/1669557492011822113133948/

       常用的宏定义,在windef.h中已经给出定义,使用时只需包括该头文件或者直接包括Windows.h即可。里面已经给出的宏定义包括:max()、min()、MAKEWORD(),MAKELONG(),LOWORD(),HIWORD(),LOBYTE(),HIBYTE()以及其他常量定义。

4.c++中如何更好地使用宏定义?

你可以参考下面链接http://www.dewen.org/q/321/%E5%A6%82%E4%BD%95%E5%9C%A8C%2FC%2B%2B%E4%B8%AD%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E5%AE%8F%E5%AE%9A%E4%B9%89%EF%BC%9F

       也就是说:

1.求值宏要用括号括起来,避免产生二意。

2.对于带参数的宏,在宏体中引用宏参数时,最好也把参数用括号括起来,否则会产生歧义。

3.避免多次求值,应定义一个本地变量暂存所有会被引用多次的宏参数。如max()宏的安全定义为:

4.对于非求值的宏,即代码块宏,用do {....}while(0)包围代码块,防止产生意外代码。
     

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值