C宏系統缺陷

來源:互聯網
上載者:User

標籤:

這兩天稍稍看了一下boost的preprocessor庫,發覺boost那幫瘋子竟然利用各種奇技淫巧定義出各種資料類型和結構,還在上面定義出加減乘除等等各種運算,在快速探索的過程中,還瞄到了很眼熟的各種宏名:list,cons,fold_left、fold_right,估計這幫人把函數式語言的很多特性也搬上去。 本著造輪子練本領的原則,我也嘗試自己去實現各種元素,可是智商不夠,越寫越難受,最後無疾而終。 大致總結了一下,暫時發現C的宏有以下反直覺的缺點: 1、無法定義局部變數,所有宏必須在最外層定義,致使全域可見     而且沒有類似namespace的功能,命名時超頭疼     不支援多行出寫,若要多行需在每行末端加 "\" 2、不控制流,要實現迴圈、選擇非常麻煩 3、傳參機制反直覺,正常語言的傳參一般採用應用序,先完全展開參數再傳入,而C的宏參數展開過程中若遇到#或##就停止展開,如:       
1      #define BOOL(n)      BOOL##n2      #define BOOL0         03      #define BOOL1         14      #define BOOL2         15      #define BOOL3         1

 

    BOOL(n)可擷取值n的真假值 
1 #define IF(c, x, y)       IF##c(x, y)2 #define IF0(x, y)         y3 #define IF1(x, y)         x

    上面的宏是想要實現選擇控制,IF中傳入邏輯值c,若c為0則返回y, 若c為1則返回x

    假如按如下調用:  IF( BOOL(3),  "t", "f" ),按直覺此句應產生“t”,    可事與願違,   因為展開BOOL(3)時碰到##,所以直接返回BOOL3,    結果上面的宏就變成了 IF( BOOL3,  "t", "f"),按IF宏體繼續展開, 則變成了 IFBOOL3("t", "f")    最後前置處理器報錯: 找不到IFBOOL3     因此,為了能正確地把參數BOOL(3)展開為1,還需要多封裝多一層宏:    
1 #define IF(c, x, y)       IF_C(c, x, y)   2 #define IF_C(c, x, y)   IF##c(x, y)

    這樣,IF( BOOL(3),  "t", "f" )就會先展開參數,變成 IF( BOOL3,  "t", "f"),

    然後宏體展開, IF_C( BOOL3, "t", "f" ),展開參數成了, IF_C( 1, "t", "f" ),    最後才會正確地展開成 IF1( "t", "f" ) 4、缺少整數類型,若要利用計數器迴圈產生代碼時非常麻煩,首先要自己手工定義一堆整數的INC:       
1       #define INC_0 12         #define INC_1 23         #define INC_2 34         #define INC_3 45         ……………6  7         #define DEC_x x8         ………………

 

         然後再在INC_xx和DEC_xx之上定義加法,減法,        這樣做相當於需要手工利用最基本的元素構造基本方法,再將這些基本方法不停地複合嵌套,抽象出更高階的函數,        工作量跟創造語言差不多         本來創造語言還是挺有趣的一件事,可由於剛剛提過的反人類反直覺的古怪傳參機制的存在,        致使複合方法構造高階函數的過程異常痛苦,得不時留意參數展開時會不會被#和##打斷,若被打斷則需要增加一層宏來繼續展開。 5、無法實現遞迴,如:       
1    #define x y+12      #define y x+1

    則展開x時,先展開成y+1,繼續展開y,x+1+1,這時又碰到了x,前置處理器便停止展開了。

     無法實現遞迴,那利用宏實現迴圈時就變得異常冗長了。    一般來說,while迴圈和尾遞迴是等價的,所以若支援遞迴,則可用尾遞迴的形式實現迴圈,但現在不支援,    所以我們需要把尾遞迴的每一步都得親自展開,並將其手工顯示的定義成宏,如:         
1         #define WHLE(...)       WHILE##n(...)2         #define WHILE0(...)     xxxxx3         #define WHLE1(....)     WHILE0(......)4         #define WHLE2(....)     WHILE1(......)5         #define WHLE3(....)     WHILE2(......)6         ...................  

 

     這樣做不僅麻煩,而且遞迴深度也只能是一個固定值 6、c的宏只是作簡單的文本替換,所以替換到文本後可能會出現,下面就是一個最經典的例子:   
1       #define square(x)  x*x2       cout<<square(2+3)<<endl;

        替換後就變成了2+3*2+3,所以寫宏時還要注意在必要的地方加括弧。。。。。。。。。

 7、沒辦法傳function-like macro的名字,如: 
1         #define ADD(n, m)   ..........2         #define FOR(k, op,...)  ......

      若調用FOR((3,3), ADD,...),想要在FOR內部ADD(3,3),發現前置處理器會報錯,說ADD沒定義。

      也就是說函數名不能當參數傳入,當然我發現boost裡面是可以的,估計是用了什麼奇技淫巧,沒耐性看,各位大神知道的話請指點以下。

C宏系統缺陷

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.