首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C 巨集:智者的利刃,愚者的惡夢——正視巨集的價值與風險

     編輯:關於C++

前言:被誤解的「萬惡之源」

許多中階 C++ 程式設計師常掛嘴邊:「C 巨集是萬惡之首,應被廢棄」。但 Bjarne Stroustrup 只說 C++ 在特定場合提供更好方案,從未完全否定巨集價值。這句話傳訛成謬,實則是「不會用、不了解」者將責任推給工具。本文舉四例展示巨集無可替代的優雅用法。

例一:簡化深層結構存取,程式碼更精練

網路程式常見 mbuf 結構層層巢狀:


struct mbuf {
    struct m_hdr mhdr;
    union {
        struct {
            struct pkthdr MH_pkthdr;
            union {
                struct m_ext MH_ext;
                char MH_databuf[MHLEN];
            } MH_dat;
        } MH;
        char M_databuf[MLEN];
    } M_dat;
};

存取最內層 MH_databuf 需寫 M_dat.MH.MH_dat.MH_databuf,冗長且難讀。實際上這些欄位邏輯上都是 mbuf 的屬性,可「壓扁」視之。原始碼定義巨集映射:


#define m_pkthdr M_dat.MH.MH_pkthdr
#define m_pktdat M_dat.MH.MH_dat.MH_databuf
// ...

使用時直接寫 m_pktdat,簡潔明瞭。

例二:跨平台、跨編譯器的條件編譯

VC 執行期庫原始碼大量使用條件巨集處理平台差異:


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

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

無巨集則需撰寫大量平台專屬程式碼,維護成本極高。

例三:自動產生程式碼——MFC 訊息映射

MFC 以巨集實現訊息 ID 與處理函式的關聯:


#define DECLARE_MESSAGE_MAP() ...
#define BEGIN_MESSAGE_MAP(theClass, baseClass) ...
#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專家編程》經典技巧

16x16 黑白圖示以十六進位陣列儲存難以辨識:


static unsigned short stopwatch[] = { 0x07C6, 0x1FF7, ... };

定義巧妙巨集將二進位圖樣「畫」在原始碼中:


#define X )*2+1   // 1 亮
#define _ )*2     // 0 暗
#define s ((((((((((((((((0

重寫陣列:


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 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
};

程式碼即文檔,一目瞭然。用畢記得 #undef 避免污染後續代碼。

結語

水能載舟,亦能覆舟。巨集是雙面刃,關鍵在於理解其展開機制、副作用與作用域。善用巨集可解決語言機制無法觸及的問題(程式碼生成、跨平台抽象、語法糖),濫用則製造除錯噩夢。掌握好這把利刃,讓它為你服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved