宏定義#define詳解

1. # define主要功能

image
  • c語言中用到很多宏定義 ,為了頭文件被重復用到#ifndef #define,#ifdefine edfif等條件編譯
  • 宏不是語句,結(jié)尾不用加“;”,否則會被替換進進程中
  • "#'' 表示這是一條預處理指令
  • 如果寫宏不止一行,則在結(jié)尾加反斜杠使多行能連接上,但第二行要對齊,否則空格也會作為替換文本的一部分

2.無參宏

  • 無參宏即宏名之后不帶參數(shù),只是簡單的文本替換
  • typedef與#define區(qū)別
    • 兩者都可以表示數(shù)據(jù)類型 1 #define INIT1 int 2 typedef in UINT2
    • 但有時候也會有區(qū)別比如定義指針類型的變量時
#define INT1 int *
typedef int * INT2;
INT1 a1, b1;
INT2 a2, b2;
INT1 a1,b1;被替換后為 int *a1,b1,
即一個指向int類型的指針一個int類型的變量;
INT2  a2,b2;   則是兩個指向int類型的指針;

3.有參宏

  • 帶參數(shù)的宏定義,宏名中不能有空格,宏名與形參表之間也不能有空格,而形參表中形參之間可以有空格
    • 有參宏實現(xiàn)一個數(shù)的平方
#define COUNT(M) M*M 
int x=6;
print(COUNT(x+1));
print(COUNT(++X));
結(jié)果輸出:13   和56,而不是函數(shù)的輸出49
  • 原因在于預編譯器不進行技術(shù),只是進行簡單的文本替換,COUNT(x+1)被替換成COUNT(x+1*x+1);
  • CUNT(++x)被替換成++x++x即為78=56而不是想要的7*7=49,連續(xù)前置自加加兩次;
  • 解決辦法是用括號將整個替換文本及每個參數(shù)用括號括起來但即便是加上括號也不能解決第二種情況,所以解決辦法是盡量不使用++,-等符號;
  • 函數(shù)實現(xiàn)一個數(shù)的平方
int count(int x)
{
return x*x
}

  • 有參宏與函數(shù)區(qū)別
    • 在宏定義#define COUNT(M) M*M中的形參不分配內(nèi)存單元,不做類型定義,只是簡單的文本替換,而函數(shù)int count(int x)中形參x是局部變量,會在棧區(qū)分配內(nèi)存單元,所以要做類型定義,而且實參與形參之間是值傳遞。而宏只是符號代換,不存在值傳遞。

  • 宏定義也可以定義表達式或多個語句
#define AB(a,b) a=i+5;b=j+3;   宏定義多個語句
int i=3,j=5;
int m-0,n=0;
AB(m,n);       //宏替換后為m=i+5,n=j+3;
print("m=%d,n=%d",m,n);
輸出結(jié)果:m=8,n=8

4.#運算符

  • '#' 的作用就是將#后邊的宏參數(shù)進行字符串的操作,也就是將#后邊的參數(shù)兩邊加上一對雙引號使其成為字符串。例如a是一個宏的形參,則替換文本中的#a被系統(tǒng)轉(zhuǎn)化為"a",這個轉(zhuǎn)換過程即為字符串化。
#define TEST(param) #param
char *pStr=TEST(123);
printf("pSrt=%s\n",pStr);
輸出結(jié)果為字符  ”123“

5.##運算符

  • '##' 運算符也可以用在替換文本中,它的作用起到粘合的作用,即將兩個宏參數(shù)連接為一個數(shù)
#define TEST(param1,param2) (param1##param2)
int num =TEST(12,34);
printf("num=%d\n",num);
輸出結(jié)果為:num=1234

6.可變宏:...和VA_ARGS

  • 作用主要是為了方便管理軟件中的打印信息。在寫代碼或DEBUG時通常需要將一些重要參數(shù)打印出來,但在軟件發(fā)行的時候不希望有這些打印,這時就用到可變參數(shù)宏了。
# define PR(...) printf(_VA_ARGS_)
PR("hello\n");
輸出結(jié)果:hello

*   在宏定義中,形參列表的最后一個參數(shù)為省略號...,而“_VA_ARGS_”被用在替換文本中,來表示省略號...代表了什么。


#define PR1(X,...) printf("Message"#X":"_VA_ARGS_)
double mes=10;
PR1(1,"msg=%.2f\n",msg);

輸出結(jié)果:Message1:msg=10.00

宏替換后為:printf(Message""1""msg=%.2f\n",msg);
  • 需要注意的是:省略號...只能用來替換宏的形參列表中的最后一個。如#define PR1(x,...,y)則是錯誤的。

7.成熟軟件中常用的宏定義。

  • 防止頭文件被重復包含
#ifndef COMDEF_H 
#define COMDEF_H
//頭文件的內(nèi)容

#endif
  • 得到一個制定地址上的一個字節(jié)或字
 #define MEM_B(X) (*((byte*)(x)))
 #define MEM_W(X) (*((word*)(x)))
  • 求最大值與最小值
 #define MAX(x,y)  ((x)>(y)?(x):(y))
 #define MIN(x,y)  ((x)<(y)?(x):(y))
  • 得到一個結(jié)構(gòu)體中field所占用的字節(jié)數(shù)
 #define FSIZ(type,field)  sizeof(((type*)0)->field)
  • 得到一個field在結(jié)構(gòu)體中的偏移量
 #define FPOS(type,field)\
                     ((dword)&(((type*)0)->field)
  • 按照LSB格式把兩個字節(jié)轉(zhuǎn)化為一個word
 #define FLIPW(ray) (((word)(ray)[0]*256)+(ray)[1])
  • 按照LSB格式將一個WORD轉(zhuǎn)化為兩個字節(jié)
 #define FLOPW(ray,val)  (ray)[0]=((val)/256);(ray)[1]=((val)&0xFF)
  • 得到一個變量的地址
 #define B_PTR(var) ((byte*)(void*)&(var))
 #define W_PTR(var) ((word*)(void*)&(var))
  • 得到一個字的高位與低位字節(jié)
 #define WORD_LO(xxx) ((byte)((word)(xxx)&255))
 #define WORD_HI(xxx) ((byte)((word)(xxx)>>8))
  • 用宏得到一個數(shù)組所含的元素個數(shù)
 #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容