參考:
例如:#include
#include
#define string "hello\
world\
i love u\n"
int main()
執行結果:
helloworld i love u
分割線因為對於乙個大程式而言,我們可能要定義很多常量( 不管是放在原始檔還是標頭檔案 ),那麼我們有時考慮定義某個常量時,我們就必須返回檢查原來此常量是否定義,但這樣做很麻煩.if defined巨集正是為這種情況提供了解決方案.舉個例子,如下:
#define ....
#define ....
....
....
#define a 100
....
此時,我們要檢查a是否定義(假設我們已經記不著這點了),或者我們要給a乙個不同的值,就加入如下句子
#if defined a
#undef a
#define a 200
#endif
上述語句檢驗a是否被定義,如果被定義,則用#undef語句解除定義,並重新定義a為200
同樣,檢驗a是否定義:
#ifndef a //如果a沒有被定義
#define a 100
#endif
以上所用的巨集中:#undef為解除定義,#ifndef是if not defined的縮寫,即如果沒有定義。
這就是#if defined 的唯一作用!
#define a 100
#endif
以上所用的巨集中:#undef為解除定義,#ifndef是if not defined的縮寫,即如果沒有定義。
這就是#if defined 的唯一作用!
1) #if defined ***_***
#endif
是條件編譯,是根據你是否定義了***_***這個巨集,而使用不同的**。
一般.**件裡最外層的
#if !defined ***_***
#define ***_***
#endif
是為了防止這個.h標頭檔案被重複include。
2) #error ***x
是用來產生編譯時錯誤資訊***x的,一般用在預處理過程中;
例子:
#if !defined(__cplusplus)
#error c++ compiler required.
#endif
1 防止乙個標頭檔案被重複包含
#ifndef bodydef_h
#define bodydef_h
//標頭檔案內容
#endif
2 得到指定位址上的乙個位元組或字
#define mem_b( x ) ( *( (byte *) (x) ) )
#define mem_w( x ) ( *( (word *) (x) ) )
用法如下:
#include
#include
#define mem_b(x) (*((byte*)(x)))
#define mem_w(x) (*((word*)(x)))
int main()
3 得到乙個field在結構體(struct)中的偏移量
#define offsetof( type, field ) ( (size_t) &(( type *) 0)-> field )
((type *)0)->field:對應域的變數。
&((type *)0)->field:取該變數的位址,其實就等於該域相對於0位址的偏移量。
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*/
一。需要注意的是凡巨集定義裡有用'#'或'##'的地方巨集引數是不會再展開.
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 #i nclude
這行會被展開為:
printf("int max: %s/n", "int_max");
printf("%s/n", cons(a, a)); // compile error
這一行則是:
printf("%s/n", int(aea));
int_max和a都不會再被展開, 然而解決這個問題的方法很簡單. 加多一層中間轉換巨集.
加這層巨集的用意是把所有巨集的引數在這層裡全部展開, 那麼在轉換巨集裡的那乙個巨集(_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型的最大值,為乙個變數 #i nclude
輸出為: 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__在第二層才能被解開;
核心 巨集定義 container of
container of 1.1 container of介紹 定義 container of在linux核心的include linux kernel.h中定義。define container of ptr,type,member 說明 根據 結構體 type 變數 中的 域成員變數 membe...
linux 核心 THIS MODULE巨集定義詳解
結構體struct module在核心中代表乙個核心模組,通過insmod 實際執行init module系統呼叫 把自己編寫的核心模組插入核心時,模組便與乙個 struct module結構體相關聯,並成為核心的一部分。下面是結構體struct module的完整定義,接下來會逐個解釋 struc...
abs int 巨集定義 巨集定義和巨集方法
巨集定義和巨集方法 定義機型 define is iphone5 uiscreen instancesrespondtoselector selector currentmode cgsizeequaltosize cgsizemake 640,1136 uiscreen mainscreen cu...