今天在網上突然發現了下面幾個關於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 識別符號 字...