亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C宏——智者的利刃,愚者的惡夢

2019-11-17 05:10:09
字體:
來源:轉載
供稿:網友

  水平不高不低的C++程序員最喜歡掛在嘴上的一句話就是:C宏,萬惡之首,錯誤的開端,應該被廢棄。

  請注重,我用了一句不敬的修飾語“水平不高不低的”。為什么這么說?因為水平低都插不上話,都在在靜靜地聽老前輩布道呢。水平高的,比如Bane Stroustrup老人家,也只是說若干種場合下C++語言能夠提供比C macro更好的解決方案,而沒有完全否定C macro的價值。但是話就怕傳來傳去,一傳就走樣。久而久之,就被傳成上面那句話。其實說來也很好笑:java程序員經常說java比C++好,說C++手動釋放內存老搞內存泄漏;C++程序員便反駁說,那是你水平低不會用。但是談到C宏,水平不高不低的C++程序員居然也走java的老路了——明明是自己不會用,自己知道的少,卻把責任推卸到C宏上。你自己笨我管不著,但是錯誤的言論假如誤導后人就不好了吧。

  本文就舉幾個簡單的使用C宏的例子,假如這些例子用C++不用宏的語法能更好的解決,那么你一定要回復blog告訴我,這樣下次我就不亂說話了。否則,笑笑很生氣,后果很嚴重。

  例一、用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宏,實現跨平臺和編譯器的需要這方面的例子太好舉了,一舉一大摞,就從VC的庫源碼中隨意copy一段出來吧。

#ifndef _CRTAPI1
#if _MSC_VER >= 800 && _M_IX86 >= 300
#define _CRTAPI1 __cdecl
#else /* _MSC_VER >= 800 && _M_IX86 >= 300 */
#define _CRTAPI1
#endif /* _MSC_VER >= 800 && _M_IX86 >= 300 */
#endif /* _CRTAPI1 */

#ifndef _SIZE_T_DEFINED
typedef unsigned int size_t;
#define _SIZE_T_DEFINED
#endif /* _SIZE_T_DEFINED */

#ifndef _MAC
#ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
#define _WCHAR_T_DEFINED
#endif /* _WCHAR_T_DEFINED */
#endif /* _MAC */

#ifndef _NLSCMP_DEFINED
#define _NLSCMPERROR 2147483647 /* currently == INT_MAX */
#define _NLSCMP_DEFINED
#endif /* _NLSCMP_DEFINED */
  請問,這些指示宏如何取代呢?假如真的是沒有了這些宏,實現起來就更麻煩了吧。

  例三、用C宏,自動生成代碼這方面的例子也是多得很,不過有鑒于很多朋友不用很多編譯器,不做嵌入式的開發,我就舉個win平臺的例子吧。我們知道MFC實現了windows的消息映射,比如:

ON_COMMAND(IDM_ABOUT, OnAbout)
ON_COMMAND(IDM_FILENEW, OnFileNew)
  它是如何實現的IDM_ABOUT和OnAbout的關聯的呢?這要用到幾個宏。


#define DECLARE_MESSAGE_MAP() /
PRivate: /
static const AFX_MSGMAP_ENTRY _messageEntries[]; /
protected: /
static AFX_DATA const AFX_MSGMAP messageMap; /
virtual const AFX_MSGMAP* GetMessageMap() const; /

#define BEGIN_MESSAGE_MAP(theClass, baseClass) /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return &theClass::messageMap; } /
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = /
{ &baseClass::messageMap, &theClass::_messageEntries[0] }; /
AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = /
{ /

#define ON_COMMAND(id, memberFxn) /
{ WM_COMMAND, 0, (Word)id, (WORD)id, AfxSig_vv, (AFX_PMSG)memberFxn },

#define END_MESSAGE_MAP() /
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /
}; /
#define DECLARE_MESSAGE_MAP() /
private: /
static const AFX_MSGMAP_ENTRY _messageEntries[]; /
protected: /
static AFX_DATA const AFX_MSGMAP messageMap; /
virtual const AFX_MSGMAP* GetMessageMap() const; /

#define BEGIN_MESSAGE_MAP(theClass, baseClass) /
const AFX_MSGMAP* theClass::GetMessageMap() const /
{ return &theClass::messageMap; } /
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = /
{ &baseClass::messageMap, &theClass::_messageEntries[0] }; /
AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = /
{ /

#define ON_COMMAND(id, memberFxn) /
{ WM_COMMAND, 0, (WORD)id, (WORD)id, AfxSig_vv, (AFX_PMSG)memberFxn },

#define END_MESSAGE_MAP() /
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /
}; /
  嘿嘿,就這么幾個宏,就構造出一個消息數組來。

  例四、用C宏,智者思維的火花說了半天了,嘴皮子都干了,舉個例子大家輕松一下——看看人家老外是怎么用宏的。這個例子摘自《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語言具有八進制、十進制和十六進制常量,但沒有二進制常量,否則的話倒是一種更為簡單的繪制圖形模式的方法。

  假如抓住書的右上角,并斜這看這一頁,可能會猜測這是一個用于流行窗口系統的“cursor busy”小秒表圖形。我是在幾年前從Usenet comp.lang.c新聞組學到這個技巧的。

  千萬不要忘了在繪圖結束后清除這些宏定義,否這很可能會給你后面的代碼帶來不可猜測的后果。

  好了,今天的廢話就到這里了。水能載舟,亦能覆舟,把握好手中的雙刃劍,讓它好好的為你服務吧,別割破了手。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品久久久久久久玫瑰园| 亚洲老板91色精品久久| 午夜精品一区二区三区在线播放| 欧美最猛性xxxxx亚洲精品| 欧美综合第一页| 久久久www成人免费精品| 精品国产一区二区三区久久| 欧美一级成年大片在线观看| 欧美丝袜一区二区| 奇米影视亚洲狠狠色| 欧美激情一区二区三级高清视频| 欧美激情亚洲激情| 91精品成人久久| 久久精品99久久久香蕉| 欧美性理论片在线观看片免费| 色综合久综合久久综合久鬼88| 精品视频偷偷看在线观看| 亚洲欧美精品一区| 91精品国产综合久久香蕉的用户体验| www国产91| 热99精品里视频精品| 97色在线观看| 另类视频在线观看| 亚洲日本中文字幕免费在线不卡| 亚洲精品天天看| 国产成人极品视频| 亚洲精品wwwww| 国产精品精品国产| 国产精自产拍久久久久久蜜| 亚洲成人精品久久久| 国产日韩中文字幕在线| 国产91色在线|免| 国产精品久久久久久久久久免费| 成人黄色在线播放| 国产suv精品一区二区三区88区| 最近的2019中文字幕免费一页| 亚洲电影av在线| 日韩成人中文电影| 日韩成人高清在线| 国产婷婷97碰碰久久人人蜜臀| 久久艳片www.17c.com| 久久国产加勒比精品无码| 国产精品a久久久久久| 91香蕉国产在线观看| 亚洲电影免费观看高清完整版在线观看| 亚洲综合中文字幕在线| 成人国产精品日本在线| 91欧美激情另类亚洲| 欧美日韩国产中文精品字幕自在自线| 亚洲欧美三级伦理| 亚洲美女精品久久| 国产免费亚洲高清| 亚洲成人国产精品| 亚洲视频精品在线| 北条麻妃久久精品| 91理论片午午论夜理片久久| 欧美激情中文字幕乱码免费| 久久人人爽人人爽人人片av高清| 日韩久久精品电影| 亚洲理论电影网| 精品少妇v888av| 在线精品国产欧美| 热久久美女精品天天吊色| 91av在线视频观看| 亚洲精品www| 精品国产乱码久久久久久虫虫漫画| 欧美韩国理论所午夜片917电影| 日韩精品极品视频免费观看| 中文字幕日韩av| 国产日韩欧美电影在线观看| 中文字幕亚洲一区在线观看| 中文字幕在线看视频国产欧美| 日本高清久久天堂| 欧美在线性视频| 97涩涩爰在线观看亚洲| 国产视频精品自拍| 日本成人免费在线| 91伊人影院在线播放| 国产视频在线观看一区二区| 91成品人片a无限观看| 九九热r在线视频精品| 成人av番号网| 久久99国产精品自在自在app| 中文字幕欧美日韩精品| 77777少妇光屁股久久一区| 久久久精品久久| 粉嫩老牛aⅴ一区二区三区| 国产精品视频公开费视频| 98精品国产高清在线xxxx天堂| 91亚洲精品一区二区| 日韩av免费在线播放| 欧洲美女7788成人免费视频| 欧美精品一本久久男人的天堂| 久久99国产综合精品女同| 亚洲欧美日韩一区二区在线| 日本国产高清不卡| 成人午夜小视频| 91国产精品91| 在线成人激情黄色| 欧美日韩国产中文字幕| 日韩h在线观看| 久久香蕉频线观| 亚洲性av在线| 国产精品高潮呻吟久久av无限| 欧美性极品xxxx娇小| 欧美精品videofree1080p| 欧美超级乱淫片喷水| 日韩精品在线视频美女| 欧美激情综合色| 成人黄色影片在线| 日韩成人xxxx| 性夜试看影院91社区| 欧美精品videossex88| 美女撒尿一区二区三区| 欧美亚洲另类在线| 久久青草福利网站| 91在线视频精品| 日韩在线观看视频免费| 欧美成人免费全部观看天天性色| 视频一区视频二区国产精品| 国产精品视频色| 成人激情视频在线观看| 国产欧美一区二区三区久久人妖| 国产精品视频地址| 91精品国产91久久久久久| 亚洲精品一区二区久| 中文字幕亚洲综合| 国产精品偷伦视频免费观看国产| 国产精品偷伦一区二区| 欧美理论电影在线观看| 国产成人avxxxxx在线看| 日本精品va在线观看| www.久久久久久.com| 韩国三级电影久久久久久| 一区二区av在线| 欧美成人精品在线| 国产视频自拍一区| 国产精品美女无圣光视频| 国产一区二区在线免费视频| 九九九久久久久久| 亚洲精品自拍第一页| 91免费观看网站| 成人免费视频在线观看超级碰| 欧美激情影音先锋| 911国产网站尤物在线观看| 久久亚洲综合国产精品99麻豆精品福利| 亚洲精品在线看| 日本欧美精品在线| 亚洲综合成人婷婷小说| 2019亚洲男人天堂| 黄色成人av在线| 亚洲第一av网| 亚洲美女性生活视频| 亚洲国产婷婷香蕉久久久久久| 国产精品 欧美在线| 91久久久在线| 国产女精品视频网站免费| 国产成人精品免费久久久久| 亚洲第一偷拍网| 91色视频在线导航| 亚洲美女av在线| 黑人狂躁日本妞一区二区三区| 亚洲第一天堂无码专区| 国产日韩精品在线观看|