C小加

厚德 博学 求真 至善 The bright moon and breeze
posts - 145, comments - 195, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

避免使用宏

Posted on 2011-11-19 13:52 C小加 阅读(13030) 评论(6)  编辑 收藏 引用

概述:

        宏是C和C++语言的抽象设施中最生硬的工具,它是披着函数外衣的饥饿的狼,很难驯服,它会我行我素地游走于各处。要避免使用宏。

讨论:

        在C++中,几乎从不需要使用宏。

        可以用const或者enum定义易于理解的常量,用inline避免函数调用的开销,用template指定函数系列和类型系列,用namespace避免名称冲突。

    C++的宏的主要问题在于,它们表面上看起来很好,而实际上做的却是另一回事。宏会忽略作用域,忽略类型系统,忽略所有其他的语言特性和规则,而且会劫持它为文件其余部分所定义(#define)的符号。宏调用看上去很像符号或者函数调用,但实际上并非如此。宏不太“卫生”,也就是说,它会根据自己被使用时所处的环境引人注目而且令人惊奇地展开为各种东西。宏需要进行文本替换,因此编写远距离也正确的宏接近于一种魔法,而精通这种魔法既无意义又无趣味。

    不少人认为与模板相关的错误都是最难以解读的,他们可能还没有看到误写和误用的宏所引起的那些错误。模板是C++类型系统的一部分,因此编译器可以更好地对它们进行处理,而宏天生是与语言本身割裂开来的,因此很难处理。更糟的是,与模板不同,宏可能展开为在偶然情况下能够编译的“传输线噪音”。最后,宏中的错误可能只有在宏展开之后才能被报告出来,而不是在定义时。

     即使在极少的情况下,有正当理由编写宏,也决不要考虑编写一个以常见词或者缩略语为名字的宏。尽可能快的取消宏的定义(#undef)。

示例:

    1、定义一个宏#define  min(n, m)    ((n) < (m) ? (n) : (m)) 

            定义两个变量a和b,min(++a, b) 传入之后是这样 ((++a) < (b) ? (++a) : (b))   如果++a小于b的话,a就自加了两次,很明显不符合宏使用的初衷。

    2、将模板实例化转给宏,宏仅能理解C语言的小括号和方括号,并将其进行匹配。然而,C++又定义了一个新的括号结构,即模板中使用的尖括号<和>。宏无法正确的匹配它们,这意味着在下面的宏调用中:

       MACRO(Foo<int,double>)

       宏会认为传给自己的是两个参数,即Foo<int和double>,而事实上该结构是一个C++实体。

例外情况:

    宏仍然是几个重要任务的唯一解决方案,比如#include保护符,条件编译中的#ifdef和#ifndef,以及assert的实现。

    在条件编译中,要避免在代码中到处杂乱地插入#ifdef。相反,应该对代码进行组织,利用宏在驱动一个公共接口的多个实现,然后始终使用该接口。

    如果不想到处复制粘贴代码段,那么可以使用宏,但要非常小心。
       


      来自:《C++编程规范》

Feedback

# re: 避免使用宏  回复  更多评论   

2011-11-21 09:13 by yanxinmeng
最近写的代码 涉及到一些别人写的宏。 其中还有 临时变量。。。

# re: 避免使用宏  回复  更多评论   

2011-11-21 16:04 by C小加
使用的时候要注意,有时候会得到莫名其妙的答案,你还不知道该怎么改@yanxinmeng

# re: 避免使用宏[未登录]  回复  更多评论   

2011-12-07 08:48 by alex
转载请注明出处。

这段话 引自 《C++编程规范101条规则、准则最佳实践》 书里面的第16条: 避免使用宏。

很不认同,转载不标明出处的。不尊重原作者,对读者也不负责。

# re: 避免使用宏  回复  更多评论   

2012-03-04 12:04 by 泡菜
规范是死的,人是活的!!

举个例子;不少书/规范主张不用goto...有空下个Linux内核代码看看,goto遍地都是!Linux内核就是依靠goto一点一点把性能给压榨出来的(至于是如何压榨的自己想想,俺不解释)

不少主张不用goto的,有几块能达到写内核的水平??

# re: 避免使用宏  回复  更多评论   

2012-03-04 13:28 by C小加
听人说搞嵌入式的用的不是循环,是goto,呵呵。自从老师说不要用goto,我就从来都没用过。看来goto是提高效率的利器啊,可是危险性就不用考虑么?疑惑@泡菜

# re: 避免使用宏  回复  更多评论   

2012-03-15 18:34 by coreBugZJ
个人觉得,各种机制都是有其存在的价值,不必挢枉过正。

# re: 避免使用宏  回复  更多评论   

2012-03-16 10:09 by C小加
赞同。宏在嵌入式中宏也占很大比重。这只是对一些初学者来说的,使用宏的时候一定要万分小心。
@coreBugZJ

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理