一些比較精妙的巨集定義

2022-05-18 07:10:56 字數 3644 閱讀 8338

今天在網上突然發現了下面幾個關於c**中的巨集定義的說明,回想下,好像在系統的**中也見過這些零散的定義,但沒有注意,看到別人總結了下,發現果然很有用,雖然不知有的道可用與否,但也不失為一種手段,所以就先把它摘抄下來,增加一點見識:

1,防止乙個標頭檔案被重複包含 

#ifndef bodydef_h 

#define bodydef_h 

//標頭檔案內容 

#endif 

2,得到指定位址上的乙個位元組或字 

#define  mem_b( x )  ( *( (byte *) (x) ) ) 

#define  mem_w( x )  ( *( (word *) (x) ) ) 

3,得到乙個field在結構體(struct)中的偏移量 

#define fpos( type, field ) ( (dword) &(( type *) 0)-> field )

4,得到乙個結構體中field所占用的位元組數 

#define fsiz( type, field ) sizeof( ((type *) 0)->field ) 

5,得到乙個變數的位址(word寬度) 

#define  b_ptr( var )  ( (byte *) (void *) &(var) ) 

#define  w_ptr( var )  ( (word *) (void *) &(var) ) 

6,將乙個字母轉換為大寫 

#define  upcase( c ) ( ((c) >= ''a'' && (c) <= ''z'') ? ((c) - 0x20) : (c) ) 

7,判斷字元是不是10進值的數字 

#define  decchk( c ) ((c) >= ''0'' && (c) <= ''9'') 

8,判斷字元是不是16進值的數字 

#define  hexchk( c ) ( ((c) >= ''0'' && (c) <= ''9'') ||((c) >= ''a'' && (c) <= ''f'') ||((c) >= ''a'' && (c) <= ''f'') ) 

9,防止溢位的乙個方法 

#define  inc_sat( val )  (val = ((val)+1 > (val)) ? (val)+1 : (val)) 

10,返回陣列元素的個數 

#define  arr_size( a )  ( sizeof( (a) ) / sizeof( (a[0]) ) ) 

11,使用一些巨集跟蹤除錯 

ansi標準說明了五個預定義的巨集名。它們是: 

_line_ (兩個下劃線),對應%d

_file_     對應%s

_date_   對應%s

_time_    對應%s

_stdc_

巨集中"#"和"##"的用法

我們使用#把巨集引數變為乙個字串,用##把兩個巨集引數貼合在一起.

#define str(s)     #s 

#define cons(a,b)  int(a##e##b) 

printf(str(vck));           // 輸出字串"vck" 

printf("%d\n", cons(2,3));  // 2e3 輸出:2000

當巨集引數是另乙個巨集的時候 

需要注意的是凡巨集定義裡有用"#"或"##"的地方巨集引數是不會再展開. 

#define a          (2) 

#define str(s)     #s 

#define cons(a,b)  int(a##e##b) 

printf("%s\n", cons(a, a));               // compile error  

這一行則是: 

printf("%s\n", int(aea)); 

int_max和a都不會再被展開, 然而解決這個問題的方法很簡單. 加多一層中間轉換巨集. 

加這層巨集的用意是把所有巨集的引數在這層裡全部展開, 那麼在轉換巨集裡的那乙個巨集(_str)就能得到正確的巨集引數

#define str(s)      _str(s)          // 轉換巨集 

#define cons(a,b)   _cons(a,b)       // 轉換巨集 

printf("int max: %s\n", str(int_max));          // int_max,int型的最大值,為乙個變數 #include

輸出為: 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)  

enum idd; 

typedef struct msgmsg;

msg _msg = ; 

相當於: 

msg _msg = , 

};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]; 

巨集定義的一些用法

c及c 通過預處理器提供了一些語言功能,最常用的有 include指令,用於包含標頭檔案,其他如 define及巨集定義,也被稱為巨集替換,當編譯器編譯到帶巨集定義的語句時,會直接替換為定義語句.例如,假如我定義有 define maxlength 100,那麼,在編譯器編譯到所有maxlength...

vxworks一些巨集定義位址

ram high adrs記憶體起始位址 boot執行位址 ram low adrs vxworks執行位址 user reserved mem使用者保留記憶體區域 熱啟動可以保留除錯資訊 local mem local adrs記憶體起始位址 加入元件memory show routine就可用s...

關於巨集定義的一些理解

以前也聽說過巨集,但是沒有引起重視,現在看到什麼巨集之類的,感覺很是高深,於是查詢資料n久,算是對其乙個大致的了解。巨集定義是c提供的三種預處理功能的其中一種,這三種預處理包括 巨集定義 檔案包含 條件編譯。1.不帶引數 巨集定義又稱為巨集代換 巨集替換,簡稱 巨集 格式 define 識別符號 字...