宏定義#define詳解


  1. #define主要功能

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

  2.無參宏

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

    • INT1 a1,b1;被替換后為 int *a1,b1;即一個指向int類型的指針一個int類型的變量
    • INT2  a2,b2;則是兩個指向int類型的指針

3.有參宏

  • 帶參數的宏定義,宏名中不能有空格,宏名與形參表之間也不能有空格,而形參表中形參之間可以有空格

 

  • 有參宏實現一個數的平方
    • 1 #define COUNT(M) M*M
      2 int x=6;
      3 print(COUNT(x+1));
      4 print(COUNT(++X));
      5 結果輸出:13   和56
      而不是函數的輸出49和

      • 原因在於預編譯器不進行技術,只是進行簡單的文本替換,COUNT(x+1)被替換成COUNT(x+1*x+1)
      • CUNT(++x)被替換成++x*++x即為7*8=56而不是想要的7*7=49,連續前置自加加兩次
      • 解決辦法是用括號將整個替換文本及每個參數用括號括起來但即便是加上括號也不能解決第二種情況,所以解決辦法是盡量不使用++,-等符號
  • 函數實現一個數的平方
    • 1 int count(int x)
      2 {
      3 return x*x
      4 }

 

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

 

  • 宏定義也可以定義表達式或多個語句
    • #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);
      
      輸出結果:m=8,n=8

  4.#運算符

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

     

5.##運算符

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

     

6.可變宏:...和_VA_ARGS_

  • 作用主要是為了方便管理軟件中的打印信息。在寫代碼或DEBUG時通常需要將一些重要參數打印出來,但在軟件發行的時候不希望有這些打印,這時就用到可變參數宏了。
  • 1 # define PR(...) printf(_VA_ARGS_)
    2 PR("hello\n");
    3 
    4 輸出結果:hello
    • 在宏定義中,形參列表的最后一個參數為省略號...,而“_VA_ARGS_”被用在替換文本中,來表示省略號...代表了什么。
  • 1 #define PR1(X,...) printf("Message"#X":"_VA_ARGS_)
    2 double mes=10;
    3 PR1(1,"msg=%.2f\n",msg);
    4 
    5 輸出結果:Message1:msg=10.00
    6 
    7 宏替換后為:printf(Message""1""msg=%.2f\n",msg);
    • 需要注意的是:省略號...只能用來替換宏的形參列表中的最后一個。如#define PR1(x,...,y)則是錯誤的。



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

  • 防止頭文件被重復包含
    • 1 #ifndef COMDEF_H
      2 
      3 #define COMDEF_H
      4 //頭文件的內容
      5 
      6 #endif
  • 得到一個制定地址上的一個字節或字
    • 1 #define MEM_B(X) (*((byte*)(x)))
      2 #define MEM_W(X) (*((word*)(x)))
  • 求最大值與最小值
    • 1 #define MAX(x,y)  ((x)>(y)?(x):(y))
      2 #define MIN(x,y)  ((x)<(y)?(x):(y))
  • 得到一個結構體中field所占用的字節數
    • 1 #define FSIZ(type,field)  sizeof(((type*)0)->field)
  • 得到一個field在結構體中的偏移量
    • 1 #define FPOS(type,field)\
      2                     ((dword)&(((type*)0)->field)
  • 按照LSB格式把兩個字節轉化為一個word
    • 1 #define FLIPW(ray) (((word)(ray)[0]*256)+(ray)[1])
  • 按照LSB格式將一個WORD轉化為兩個字節
    • 1 #define FLOPW(ray,val)  (ray)[0]=((val)/256);(ray)[1]=((val)&0xFF)
  • 得到一個變量的地址
    • 1 #define B_PTR(var) ((byte*)(void*)&(var))
      2 #define W_PTR(var) ((word*)(void*)&(var))
  • 得到一個字的高位與低位字節
    • 1 #define WORD_LO(xxx) ((byte)((word)(xxx)&255))
      2 #define WORD_HI(xxx) ((byte)((word)(xxx)>>8))
  •  用宏得到一個數組所含的元素個數
    • 1 #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM