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

首頁 > 編程 > C++ > 正文

C++中宏的使用問題詳解

2020-05-23 14:04:15
字體:
來源:轉載
供稿:網友
宏替換是C/C++系列語言的技術特色,C/C++語言提供了強大的宏替換功能,源代碼在進入編譯器之前,要先經過一個稱為“預處理器”的模塊,這個模塊將宏根據編譯參數和實際編碼進行展開,展開后的代碼才正式進入編譯器,進行詞法分析、語法分析等等。
 

宏不遵循C++中關于范圍和類型的規則。這經常導致一些微妙的或不那么微妙的問題。因此,C++提供更適合其他的C++(譯注:原文為the rest of C++,當指C++除了兼容C 以外的部分)的替代品,例如內聯函數、模板與名字空間。

考慮一下:

#include "someheader.h"struct S {  int alpha;  int beta;};

如果某人(不明智地)地寫了一個叫“alpha”或“beta”的宏,那么它將不會被編譯,或者被錯誤地編譯,產生不可預知的結果。例如,“someheader.h”可能包含:

  #define alpha 'a'  #define beta b[2]

將宏(而且僅僅是宏)全部大寫的習慣,會有所幫助,但是對于宏并沒有語言層次上的保護機制。例如,雖然成員的名字包含在結構體的內部,但這無濟于事:在編譯器能夠正確地辨別這一點之前,宏已經將程序作為一個字符流進行了處理。順便說一句,這是C 和C++程序開發環境和工具能夠被簡化的一個主要原因:人與編譯器看到的是不同的東西。

不幸的是,你不能假設別的程序員總是能夠避免這種你認為“相當白癡”的事情。例如,最近有人報告我,他們遇到了一個包含goto 的宏。我也見過這種情況,而且聽到過一些——在很脆弱的時候——看起來確實有理的意見。例如:

#define prefix get_ready(); int ret__#define Return(i) ret__=i; do_something(); goto exit#define suffix exit: cleanup(); return ret__void f(){  prefix;  // ...  Return(10);  // ...  Return(x++);  //...  suffix;}

作為一個維護的程序員,就會產生這種印象;將宏“隱藏”到一個頭文件中——這并不罕見——使得這種“魔法”更難以被辨別。

一個常見的微妙問題是,一個函數風格的宏并不遵守函數參數傳遞的規則。例如:

#define square(x) (x*x)void f(double d, int i){  square(d); // 好  square(i++); // 糟糕:這表示 (i++*i++)  square(d+1); //糟糕:這表示(d+1*d+1); 也就是 (d+d+1)  // ...}

“d+1”的問題,可以通過在“調用”時或宏定義時添加一對圓括號來解決:

  #define square(x) ((x)*(x)) /*這樣更好 */

但是, i++被執行了兩次(可能并不是有意要這么做)的問題仍然存在。

是的,我確實知道有些特殊的宏并不會導致C/C++預處理宏這樣的問題。但是,我無心去發展C++中的宏。作為替代,我推薦使用C++語言中合適的工具,例如內聯函數,模板,構造函數(用來初始化),析構函數(用來清除),異常(用來退出上下文環境),等等。

好了,今天就先到這里,以后我們再來更深入的探討這個問題



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大悟县| 湟中县| 五峰| 江安县| 延长县| 郑州市| 潜江市| 克拉玛依市| 台安县| 通江县| 塔城市| 金湖县| 库尔勒市| 达拉特旗| 那曲县| 长寿区| 崇左市| 沾化县| SHOW| 渑池县| 都安| 利川市| 壤塘县| 华坪县| 兰西县| 蒙自县| 勐海县| 康马县| 新营市| 黎城县| 财经| 大同市| 元朗区| 佛学| 璧山县| 山西省| 东海县| 佛冈县| 余庆县| 崇左市| 龙陵县|