王为民的技术和生活空间

练内功、勤实战、学习数学、迸发创新意识、注重团队精神,把握好前进的方向…………

用户操作
[即时聊天] [发私信] [加为好友]
王为民ID:ningboweimin
93346次访问,排名1066,好友17人,关注者23人。
08.05-至今 深圳清华力合通信有限公司 MMI开发
07.09--08.05 深圳胜博联技术有限公司 MTK MMI开发。
05.12-07.08 宁波高凌通信技术有限公司工作,主要负责双膜(GSM/PHS)手机及小灵通的研究和开发,平台涉及展讯及东芝。
05.6-05.12 国家数字交换系统工程技术研究中心(NDSC) 主要从事路由器路由协议调试和开发,具体负责多协议标志交换(MPLS)模块,深入了解了其信令和控制协议——标记分发协议(LDP)。
ningboweimin的文章
原创 104 篇
翻译 1 篇
转载 105 篇
评论 18 篇
王为民的公告
清新家园

关注C语言,关注生活。 QQ:94686732 Msn:wwmzxy@hotmail.com
wangweiminxy@gmail.com
XING
最近评论
sap99:www.sap99.com/,SAP99资料多多

SAP免费资料下载
http://www.sap99.com

有很多的学习资料,推荐一下,
ningboweimin:自己顶下先。。。
wuqifeng0101:你好 不知道你能不能提供信大微电子专业的专业课试题数字电路和微机原理 谢谢!
wangseaya:真是幸福的一对啊
羡慕ing
祝福ing
sunag:天仙配
羡慕
嫂子真漂亮
吼吼
不过呢
你有点胖了
尤其是肚子
要多运动啊
文章分类
收藏
相册
户外婚礼
美丽风景
我和朋友
行网聚会
IT技术
IBM技术专家群
ITPUB
MSDN中国
VC知识库
中国Unix技术
中国系统分析师
嵌入式资讯网
红联LINUX
计算机世界
软件工程专家网
管理天地
IT经理世界
华尔街日报
好书阁
《华为真相》
《商道》
《墨迹》
《没有任何借口》
《细节决定成败》
朋友圈
My Gallery
XING宁波
军华
冰儿
可爱狼
小潘
嵐曦一尘
月光博客
朗朗星空
梅花三弄
永超
江涛
瀚海星尘
程军剑
管为为
胡雪儿
馨荣家园
网络通信
Cisco网络技术
中国3G通信网
中国协议分析网
中国通信资源网
休闲娱乐
Google黑板报
Mofile TV
人民网
英语学习网
行网中国
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 C语言的万恶之首----宏收藏

新一篇: 函数设计规则与例子 | 旧一篇: 关于二进制中“1”的个数

 C语言的万恶之首----宏

    水平不高不低的C/C++程序员最喜欢挂在嘴上的一句话就是:C宏,万恶之首,错误的开端,应该被废弃。当然,我也是水平一般的人。但是我们不能把C语言本身做为使自己程序出错的原因。如果我们出错了,那只能毫不客气地说,那是因为我们用的太不专业,用的太不仔细。那就让我们一起来看几个有关宏定义的经典的例子。我的博客里有篇文章叫《预处理器之我见》,虽然,我已经提到过宏的事情,但那篇文章中谈到的都是一些简单的宏定义,下面的定义不是出自我工作中的程序,但我决定人家用的那叫绝,所以我们一起来走进C语言的万恶之首吧。

例一、用C宏,书写代码更简洁这段代码写网络程序的朋友都很眼熟,是Net/3中mbuf的实现。

struct mbuf
{
    struct m_hdr mhdr;
    union {
        struct
        {
            struct pkthdr MH_pkthdr; /* M_PKTHDR set */
            union
            {
                struct m_ext MH_ext; /* M_EXT set */
                char MH_databuf[MHLEN];
            } MH_dat;
        } MH;
        char M_databuf[MLEN];        /* !M_PKTHER, !M_EXT*/
    } M_dat;
};

  上面的代码,假如我想访问最里层的MH_databuf,那么我必须写M_dat.MH.MH_dat.MH_databuf; 这是不是很长,很难写呀?这样的代码阅读起来也不明了。其实,对于MH_pkthdr、MH_ext、MH_databuf来说,虽然不是在一个结构层次上,但是如果我们站在mbuf之外来看,它们都是mbuf的属性,完全可以压扁到一个平面上去看。所以,源码中有这么一组宏:

#define m_next      m_hdr.mh_next
#define m_len       m_hdr.mh_len
#define m_data      m_hdr.mh_data
... ...
#define m_pkthdr    M_dat.MH.MH_pkthdr
#define m_pktdat    M_dat.MH.MH_dat.MH_databuf
... ...

这样写起代码来,是不是很精练呢!

例二、用C宏,实现跨平台和编译器的需要以及自动生成代码,这方面的例子太好举了,一下是我从工作中随便copy的一些代码。

#define __F_ADDR_(pa)   *(_VPWORD)(pa)
#define __F_ADDRDWD_(pa)  *(_VPDWORD)(pa)

#define __ADR_0x000    *(_VPWORD)(__FADR_OFFSET|0x000) 
#define __ADR_0xXXX    __ADR_0x000

#define __ADR_0x002    *(_VPWORD)(__FADR_OFFSET|0x002) 
#define __ADR_0xAAA   *(_VPWORD)(__FADR_OFFSET|0xaaa)
#define __ADR_0x555    *(_VPWORD)(__FADR_OFFSET+0x554)  


#define __F_RESET(sa)    __ADR_0x000 =0xf0

#define __F_AUTO_SELECT   __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        __ADR_0xAAA =0x90

#define __F_PROGRAM_(pa,pd)  __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        __ADR_0xAAA =0xA0;\
        *(_VPWORD)(pa)=pd

#define __F_CHIP_ERASE   __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        __ADR_0xAAA =0x80;\
        __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        __ADR_0xAAA =0x10

#define __F_SEC_ERASE_(sa)  __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        __ADR_0xAAA =0x80;\
        __ADR_0xAAA =0xaa;\
        __ADR_0x555 =0x55;\
        *(_VPWORD)(sa) =0x30

例三、学习一下老外用的宏。这是在《C专家编程》上的一个例子,很经典,所以我就用拿来主意,和大家分享一下。

     根据位模式构建图形图标(icon)或者图形(glyph),是一种小型的位模式映射于屏幕产生的图像。一个位代表图像上的一个像素。如果一个位被设置,那么它所代表的像素就是“亮”的。如果一个位被清除,那么它所代表的像素就是“暗”的。所以,一系列的整数值能够用于为图像编码。类似Iconedit这样的工具就是用于绘图的,他们所输出的是一个包含一系列整型数的ASCII文件,可以被一个窗口程序所包含。它所存在的问题是程序中的图标只是一串十六进制数。在C语言中,典型的16X16的黑白图形可能如下:

static unsigned short stopwatch[] = {
  0x07C6,
  0x1FF7,
  0x383B,
  0x600C,
  0x600C,
  0xC006,
  0xC006,
  0xDF06,
  0xC106,
  0xC106,
  0x610C,
  0x610C,
  0x3838,
  0x1FF0,
  0x07C0,
  0x0000
};

  正如所看到的那样,这些C语言常量并未有提供有关图形实际模样的任何线索。这里有一个惊人的#define定义的优雅集合,允许程序建立常量使它们看上去像是屏幕上的图形。

#define X )*2+1
#define _ )*2
#define s ((((((((((((((((0 /* For building glyphs 16 bits wide */

  定义了它们之后,只要画所需要的图标或者图形等,程序会自动创建它们的十六进制模式。使用这些宏定义,程序的自描述能力大大加强,上面这个例子可以转变为:

static unsigned short stopwatch[] =
{
  s _ _ _ _ _ X X X X X _ _ _ X X _ ,
  s _ _ _ X X X X X X X X X _ X X X ,
  s _ _ X X X _ _ _ _ _ X X X _ X X ,
  s _ X X _ _ _ _ _ _ _ _ _ X X _ _ ,
  s _ X X _ _ _ _ _ _ _ _ _ X X _ _ ,
  s X X _ _ _ _ _ _ _ _ _ _ _ X X _ ,
  s X X _ _ _ _ _ _ _ _ _ _ _ X X _ ,
  s X X _ X X X X X _ _ _ _ _ X X _ ,
  s X X _ _ _ _ _ X _ _ _ _ _ X X _ ,
  s X X _ _ _ _ _ X _ _ _ _ _ X X _ ,
  s _ X X _ _ _ _ X _ _ _ _ X X _ _ ,
  s _ X X _ _ _ _ X _ _ _ _ X X _ _ ,
  s _ _ X X X _ _ _ _ _ X X X _ _ _ ,
  s _ _ _ X X X X X X X X X _ _ _ _ ,
  s _ _ _ _ _ X X X X X _ _ _ _ _ _ ,
  s _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
};

  显然,与前面的代码相比,它的意思更为明显。标准的C语言具有八进制、十进制和十六进制常量,但没有二进制常量,否则的话倒是一种更为简单的绘制图形模式的方法。

  千万不要忘了在绘图结束后清除这些宏定义,否这很可能会给你后面的代码带来不可预测的后果。

  结束了,最后一句忠告,宏就像C语言工程师手中的一把双刃剑,如果能很好的利用它,它就会死心塌地的为你服务,不过可不要把自己的手给弄破了啊。

End

发表于 @ 2006年11月29日 15:50:00|评论(loading...)|编辑

新一篇: 函数设计规则与例子 | 旧一篇: 关于二进制中“1”的个数

评论:没有评论。

发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © 王为民