1.不帶參數的宏定義:

宏定義又稱為宏代換、宏替換,簡稱“宏”。
  格式:
  #define 標識符 字符串
  其中的標識符就是所謂的符號常量,也稱為“宏名”。
  預處理(預編譯)工作也叫做宏展開:將宏名替換為字符串
  掌握""概念的關鍵是“”。一切以換為前提、做任何事情之前先要換,準確理解之前就要“換”。
  即在對相關命令或語句的含義和功能作具體分析之前就要換:
  例:
  #define PI 3.1415926
  把程序中出現的PI全部換成3.1415926
  說明:
  1. 宏名一般用大寫
  2.使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯誤和便于修改。例如:數組大小常用宏定義
  3.預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查。
  4.宏定義末尾不加分號;
  5.宏定義寫在函數的花括號外邊,作用域為其后的程序,通常在文件的最開頭。
  6.可以用#undef命令終止宏定義的作用域
  7.宏定義可以嵌套
  8.字符串" "中永遠不包含宏
  9.宏定義不分配內存,變量定義分配內存。

2.帶參數的宏定義:

除了一般的字符串替換,還要做參數代換
  格式:
  #define 宏名(參數表) 字符串
  例如:#define S(a,b) a*b
  area=S(3,2);第一步被換為area=a*b; ,第二步被換為area=3*2;
  類似于函數調用,有一個啞實結合的過程:
  1.實參如果是表達式容易出問題
  #define S(r) r*r
area=S(a+b);第一步換為area=r*r;第二步被換為area=a+b*a+b;正確的宏定義是#define S(r) ((r)*(r))
  2.宏名和參數的括號間不能有空格
  3.宏替換只作替換,不做計算,不做表達式求解
  4.函數調用在編譯后程序運行時進行,并且分配內存。宏替換在編譯前進行,不分配內存
  5.宏的啞實結合不存在類型,也沒有類型轉換。
  6.函數只有一個返回值,利用宏則可以設法得到多個值
  7.宏展開使源程序變長,函數調用不會
  8.宏展開不占運行時間,只占編譯時間,函數調用占運行時間(分配內存、保留現場、值傳遞、返回值)

3.技巧:

define用法
  1、 用無參宏定義一個簡單的常量
  #define LEN 12
  這個是最常見的用法,但也會出錯。
  比如下面幾個知識點你會嗎?可以看下:
  (1)#define NAME "zhangyuncong"
  程序中有"NAME"則,它會不會被替換呢?
  (2)#define 0x abcd
  可以嗎?也就是說,可不可以用把標識符的字母替換成別的東西?
  (3)#define NAME "zhang
  這個可以嗎?
  (4)#define NAME "zhangyuncong"
  程序中有上面的宏定義,并且,程序里有句:
  NAMELIST這樣,會不會被替換成"zhangyuncong"LIST
  四個題答案都是否定的。
  第一個,""內的東西不會被宏替換。這一點應該大都知道。
  第二個,宏定義前面的那個必須是合法的用戶標識符
  第三個,宏定義也不是說后面東西隨便寫,不能把字符串的兩個""拆開。
  第四個:只替換標識符,不替換別的東西。NAMELIST整體是個標識符,而沒有NAME標識符,所以不替換。
  也就是說,這種情況下記住:#define 第一位置第二位置
  (1) 不替換程序中字符串里的東西。
  (2) 第一位置只能是合法的標識符(可以是關鍵字)
  (3) 第二位置如果有字符串,必須把""配對。
  (4) 只替換與第一位置完全相同的標識符
  還有就是老生常談的話:記住這是簡單的替換而已,不要在中間計算結果,一定要替換出表達式之后再算。
  2、 帶參宏一般用法
  比如#define MAX(a,b) ((a)>(b)?(a):(b))
  則遇到MAX(1+2,value)則會把它替換成:
  ((1+2)>(value)?(1+2):(value))
  注意事項和無參宏差不多。
  但還是應注意
  #define FUN(a) "a"
  則,輸入FUN(345)會被替換成什么?
  其實,如果這么寫,無論宏的實參是什么,都不會影響其被替換成”a”的命運。
  也就是說,""內的字符不被當成形參,即使它和一模一樣。
  那么,你會問了,我要是想讓這里輸入FUN(345)它就替換成"345"該怎么實現呢?
  請看下面關于#的用法
  3、 有參宏定義中#的用法
  #define STR(str) #str
  #用于把宏定義中的參數兩端加上字符串的""
  比如,這里STR(my#name)會被替換成"my#name"
  一般由任意字符都可以做形參,但以下情況會出錯:
  STR())這樣,編譯器不會把“)”當成STR()的參數。
  STR(,)同上,編譯器不會把“,”當成STR的參數。
  STR(A,B)如果實參過多,則編譯器會把多余的參數舍去。(VC++2008為例)
  STR((A,B))會被解讀為實參為:(A,B),而不是被解讀為兩個實參,第一個是(A第二個是B)。
  4、 有參宏定義中##的用法
  #define WIDE(str) L##str
  則會將形參str的前面加上L
  比如:WIDE("abc")就會被替換成L"abc"
  如果有#define FUN(a,b) vo##a##b()
  那么FUN(id ma,in)會被替換成void main()
  5、 多行宏定義:

  #define doit(m,n) for(int i=0;i<(n);++i)\
  {\
  m+=i;\
  }

4.宏中"#"和"##"的用法:

一、一般用法

我們使用#把宏參數變為一個字符串,用##把兩個宏參數貼合在一起.
用法:

#include<cstdio> 
#include<climits> 
using namespace std; 

#define STR(s)     #s 
#define CONS(a,b)  int(a##e##b) 

int main() 
{ 
    printf(STR(vck));           // 輸出字符串"vck" 
    printf("%d/n", CONS(2,3));  // 2e3 輸出:2000 
    return 0; 
} 

二、當宏參數是另一個宏的時候

需要注意的是凡宏定義里有用'#'或'##'的地方宏參數是不會再展開.

1, 非'#'和'##'的情況

#define TOW      (2) 
#define MUL(a,b) (a*b) 

printf("%d*%d=%d/n", TOW, TOW, MUL(TOW,TOW)); 
這行的宏會被展開為: 
printf("%d*%d=%d/n", (2), (2), ((2)*(2))); 

MUL里的參數TOW會被展開為(2).

2, 當有'#'或'##'的時候

#define A          (2) 
#define STR(s)     #s 
#define CONS(a,b)  int(a##e##b) 

printf("int max: %s/n",  STR(INT_MAX));    // INT_MAX #include<climits> 
這行會被展開為: 
printf("int max: %s/n", "INT_MAX"); 

printf("%s/n", CONS(A, A));               // compile error  
這一行則是: 
printf("%s/n", int(AeA)); 

INT_MAXA都不會再被展開, 然而解決這個問題的方法很簡單. 加多一層中間轉換宏.
加這層宏的用意是把所有宏的參數在這層里全部展開, 那么在轉換宏里的那一個宏(_STR)就能得到正確的宏參數.

#define A           (2) 
#define _STR(s)     #s 
#define STR(s)      _STR(s)          // 轉換宏 
#define _CONS(a,b)  int(a##e##b) 
#define CONS(a,b)   _CONS(a,b)       // 轉換宏 

printf("int max: %s/n", STR(INT_MAX));          // INT_MAX,int型的最大值,為一個變量 #include<climits> 
輸出為: int max: 0x7fffffff 
STR(INT_MAX) -->  _STR(0x7fffffff) 然后再轉換成字符串; 

printf("%d/n", CONS(A, A)); 
輸出為:200 
CONS(A, A)  -->  _CONS((2), (2))  --> int((2)e(2))

三、'#'和'##'的一些應用特例

1、合并匿名變量名

#define  ___ANONYMOUS1(type, var, line)  type  var##line

#define  __ANONYMOUS0(type, line)  ___ANONYMOUS1(type, _anonymous, line)

#define  ANONYMOUS(type)  __ANONYMOUS0(type, __LINE__)

例:ANONYMOUS(static int);  即: static int _anonymous70;  70表示該行行號;

第一層:ANONYMOUS(static int);  -->  __ANONYMOUS0(static int, __LINE__);

第二層:                        -->  ___ANONYMOUS1(static int, _anonymous, 70);

第三層:                        -->  static int  _anonymous70;

即每次只能解開當前層的宏,所以__LINE__在第二層才能被解開;

2、填充結構

#define  FILL(a)   {a, #a}


enum IDD{OPEN, CLOSE};

typedef struct MSG{

  IDD id;

  const char * msg;

}MSG;


MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};

相當于:

MSG _msg[] = {{OPEN, "OPEN"},

              {CLOSE, "CLOSE"}};

3、記錄文件名

#define  _GET_FILE_NAME(f)   #f

#define  GET_FILE_NAME(f)    _GET_FILE_NAME(f)

static char  FILE_NAME[] = GET_FILE_NAME(__FILE__);

4、得到一個數值類型所對應的字符串緩沖大小

#define  _TYPE_BUF_SIZE(type)  sizeof #type

#define  TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)

char  buf[TYPE_BUF_SIZE(INT_MAX)];

     -->  char  buf[_TYPE_BUF_SIZE(0x7fffffff)];

     -->  char  buf[sizeof "0x7fffffff"];

這里相當于:

char  buf[11];
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容