国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

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

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

  水平不高不低的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_DEFINEDtypedef unsigned int size_t;#define _SIZE_T_DEFINED#endif /* _SIZE_T_DEFINED */#ifndef _MAC#ifndef _WCHAR_T_DEFINEDtypedef 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 */
  請問,這些指示宏如何取代呢?假如真的是沒有了這些宏,實現起來就更麻煩了吧。
QQ病毒 騰訊QQ空間代碼專題 PPT教程專題 ADSL應用面面俱到 fireworks教程專題 計算機和網絡技術基礎知識
校園網專題 網吧技術專題

  例三、用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新聞組學到這個技巧的。

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永济市| 青河县| 天水市| 普定县| 宜宾县| 崇义县| 罗江县| 高要市| 阜新| 横山县| 大兴区| 环江| 湄潭县| 无锡市| 龙州县| 遂昌县| 上林县| 宜兰县| 合肥市| 天长市| 宣城市| 抚顺市| 大理市| 通许县| 高尔夫| 庄河市| 门源| 石棉县| 疏附县| 白银市| 通江县| 平谷区| 鄄城县| 花莲市| 收藏| 双辽市| 兴义市| 澄迈县| 开阳县| 沐川县| 社旗县|