




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C語(yǔ)言宏定義使用技巧寫(xiě)好C語(yǔ)言,漂亮的宏定義很重要,使用宏定義可以防止出錯(cuò),提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義。1,防止一個(gè)頭文件被重復(fù)包含#ifndef COMDEF_H#define COMDEF_H/頭文件內(nèi)容#endif2,重新定義一些類(lèi)型,防止由于各種平臺(tái)和編譯器的不同,而產(chǎn)生的類(lèi)型字節(jié)數(shù)差異,方便移植。typedef unsigned char boolean; /* Boolean value type. */typedef unsigned long int uint32; /* Unsigned 32 bit value */typedef
2、 unsigned short uint16; /* Unsigned 16 bit value */typedef unsigned char uint8; /* Unsigned 8 bit value */typedef signed long int int32; /* Signed 32 bit value */typedef signed short int16; /* Signed 16 bit value */typedef signed char int8; /* Signed 8 bit value */下面的不建議使用typedef unsigned char byte;
3、 /* Unsigned 8 bit value type. */typedef unsigned short word; /* Unsinged 16 bit value type. */typedef unsigned long dword; /* Unsigned 32 bit value type. */typedef unsigned char uint1; /* Unsigned 8 bit value type. */typedef unsigned short uint2; /* Unsigned 16 bit value type. */typedef unsigned lo
4、ng uint4; /* Unsigned 32 bit value type. */typedef signed char int1; /* Signed 8 bit value type. */typedef signed short int2; /* Signed 16 bit value type. */typedef long int int4; /* Signed 32 bit value type. */typedef signed long sint31; /* Signed 32 bit value */typedef signed short sint15; /* Sign
5、ed 16 bit value */typedef signed char sint7; /* Signed 8 bit value */3,得到指定地址上的一個(gè)字節(jié)或字#define MEM_B( x ) ( *( (byte *) (x) ) )#define MEM_W( x ) ( *( (word *) (x) ) )4,求最大值和最小值#define MAX( x, y ) ( (x) > (y) ? (x) : (y) )#define MIN( x, y ) ( (x) < (y) ? (x) : (y) )5,得到一個(gè)field在結(jié)構(gòu)體(struct)中的偏移量#
6、define FPOS( type, field ) /*lint -e545 */ ( (dword) &( type *) 0)-> field ) /*lint +e545 */6,得到一個(gè)結(jié)構(gòu)體中field所占用的字節(jié)數(shù)#define FSIZ( type, field ) sizeof( (type *) 0)->field )7,按照LSB格式把兩個(gè)字節(jié)轉(zhuǎn)化為一個(gè)Word1 / 6#define FLIPW( ray ) ( (word) (ray)0) * 256) + (ray)1 )8,按照LSB格式把一個(gè)Word轉(zhuǎn)化為兩個(gè)字節(jié)#define FLOPW(
7、 ray, val ) (ray)0 = (val) / 256); (ray)1 = (val) & 0xFF)9,得到一個(gè)變量的地址(word寬度)#define B_PTR( var ) ( (byte *) (void *) &(var) )#define W_PTR( var ) ( (word *) (void *) &(var) )10,得到一個(gè)字的高位和低位字節(jié)#define WORD_LO(*) (byte) (word)(*) & 255)#define WORD_HI(*) (byte) (word)(*) >> 8)11,返回
8、一個(gè)比X大的最接近的8的倍數(shù)#define RND8( x ) (x) + 7) / 8 ) * 8 )12,將一個(gè)字母轉(zhuǎn)換為大寫(xiě)#define UPCASE( c ) ( (c) >= 'a' && (c) <= 'z') ? (c) - 0x20) : (c) )13,判斷字符是不是10進(jìn)值的數(shù)字#define DECCHK( c ) (c) >= '0' && (c) <= '9')14,判斷字符是不是16進(jìn)值的數(shù)字#define HEXCHK( c ) ( (c) &
9、gt;= '0' && (c) <= '9') |(c) >= 'A' && (c) <= 'F') |(c) >= 'a' && (c) <= 'f') )15,防止溢出的一個(gè)方法#define INC_SAT( val ) (val = (val)+1 > (val) ? (val)+1 : (val)16,返回?cái)?shù)組元素的個(gè)數(shù)#define ARR_SIZE( a ) ( sizeof( (a) ) / size
10、of( (a0) ) )17,返回一個(gè)無(wú)符號(hào)數(shù)n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2n)#define MOD_BY_POWER_OF_TWO( val, mod_by ) ( (dword)(val) & (dword)(mod_by)-1) )18,對(duì)于IO空間映射在存儲(chǔ)空間的結(jié)構(gòu),輸入輸出處理#define inp(port) (*(volatile byte *) (port)#define inpw(port) (*(volatile word *) (port)#define inpdw(port) (*(volatile dword *)(po
11、rt)#define outp(port, val) (*(volatile byte *) (port) = (byte) (val)#define outpw(port, val) (*(volatile word *) (port) = (word) (val)#define outpdw(port, val) (*(volatile dword *) (port) = (dword) (val)2005-9-9添加19,使用一些宏跟蹤調(diào)試A N S I標(biāo)準(zhǔn)說(shuō)明了五個(gè)預(yù)定義的宏名。它們是:_ L I N E _ F I L E _ D A T E _ T I M E _ S T D C
12、_如果編譯不是標(biāo)準(zhǔn)的,則可能僅支持以上宏名中的幾個(gè),或根本不支持。記住編譯程序也許還提供其它預(yù)定義的宏名。_ L I N E _及_ F I L E _宏指令在有關(guān)# l i n e的部分中已討論,這里討論其余的宏名。_ D AT E _宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時(shí)的日期。源代碼翻譯到目標(biāo)代碼的時(shí)間作為串包含在_ T I M E _中。串形式為時(shí):分:秒。如果實(shí)現(xiàn)是標(biāo)準(zhǔn)的,則宏_ S T D C _含有十進(jìn)制常量1。如果它含有任何其它數(shù),則實(shí)現(xiàn)是非標(biāo)準(zhǔn)的??梢远x宏,例如:當(dāng)定義了_DEBUG,輸出數(shù)據(jù)信息和所在文件所在行#ifdef _DEBUG#define D
13、EBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)#else#define DEBUGMSG(msg,date)#endif20,宏定義防止使用是錯(cuò)誤用小括號(hào)包含。例如:#define ADD(a,b) (a+b)用dowhile(0)語(yǔ)句包含多語(yǔ)句防止錯(cuò)誤例如:#difne DO(a,b) a+b;a+;應(yīng)用時(shí):if(.)DO(a,b); /產(chǎn)生錯(cuò)誤elseC(和C+)中的宏(Macro)屬于編譯器預(yù)處理的范疇,屬于編譯期概念(而非運(yùn)行期概念)。下面對(duì)常遇到的宏的使用問(wèn)題做了簡(jiǎn)單總結(jié)。 宏使用中的常見(jiàn)的基礎(chǔ)問(wèn)題
14、#符號(hào)和#符號(hào)的使用 .符號(hào)的使用 宏的解釋方法 我們能碰到的宏的使用 宏使用中的陷阱 常見(jiàn)的基礎(chǔ)性問(wèn)題: 關(guān)于#和# 在C語(yǔ)言的宏中,#的功能是將其后面的宏參數(shù)進(jìn)行字符串化操作(Stringfication),簡(jiǎn)單說(shuō)就是在對(duì)它所引用的宏變量通過(guò)替換后在其左右各加上一個(gè)雙引號(hào)。比如下面代碼中的宏: #define WARN_IF(EXP) do if (EXP) fprintf(stderr, "Warning: " #EXP "n"); while(0)那么實(shí)際使用中會(huì)出現(xiàn)下面所示的替換過(guò)程: WARN_IF (divider = 0);被替換為do
15、if (divider = 0)fprintf(stderr, "Warning" "divider = 0" "n"); while(0);這樣每次divider(除數(shù))為0的時(shí)候便會(huì)在標(biāo)準(zhǔn)錯(cuò)誤流上輸出一個(gè)提示信息。 而#被稱(chēng)為連接符(concatenator),用來(lái)將兩個(gè)Token連接為一個(gè)Token。注意這里連接的對(duì)象是Token就行,而不一定是宏的變量。比如你要做一個(gè)菜單項(xiàng)命令名和函數(shù)指針組成的結(jié)構(gòu)體的數(shù)組,并且希望在函數(shù)名和菜單項(xiàng)命令名之間有直觀的、名字上的關(guān)系。那么下面的代碼就非常實(shí)用:struct commandchar
16、 * name;void (*function) (void);#define COMMAND(NAME) NAME, NAME # _command / 然后你就用一些預(yù)先定義好的命令來(lái)方便的初始化一個(gè)command結(jié)構(gòu)的數(shù)組了:struct command commands = COMMAND(quit),COMMAND(help),.COMMAND宏在這里充當(dāng)一個(gè)代碼生成器的作用,這樣可以在一定程度上減少代碼密度,間接地也可以減少不留心所造成的錯(cuò)誤。我們還可以n個(gè)#符號(hào)連接 n+1個(gè)Token,這個(gè)特性也是#符號(hào)所不具備的。比如: #define LINK_MULTIPLE(a,b,c,
17、d) a#_#b#_#c#_#dtypedef struct _record_type LINK_MULTIPLE(name,company,position,salary);/ 這里這個(gè)語(yǔ)句將展開(kāi)為:/ typedef struct _record_type name_company_position_salary; 關(guān)于.的使用.在C宏中稱(chēng)為Variadic Macro,也就是變參宏。比如: #define myprintf(templt,.) fprintf(stderr,templt,_VA_ARGS_)/ 或者#define myprintf(templt,args.) fprint
18、f(stderr,templt,args) 第一個(gè)宏中由于沒(méi)有對(duì)變參起名,我們用默認(rèn)的宏_VA_ARGS_來(lái)替代它。第二個(gè)宏中,我們顯式地命名變參為args,那么我們?cè)诤甓x中就可以用args來(lái)代指變參了。同C語(yǔ)言的stdcall一樣,變參必須作為參數(shù)表的最有一項(xiàng)出現(xiàn)。當(dāng)上面的宏中我們只能提供第一個(gè)參數(shù)templt時(shí),C標(biāo)準(zhǔn)要求我們必須寫(xiě)成: myprintf(templt,);的形式。這時(shí)的替換過(guò)程為: myprintf("Error!n",); 替換為:fprintf(stderr,"Error!n",);這是一個(gè)語(yǔ)法錯(cuò)誤,不能正常編譯。這個(gè)問(wèn)題一般
19、有兩個(gè)解決方法。首先,GNU CPP提供的解決方法允許上面的宏調(diào)用寫(xiě)成: myprintf(templt);而它將會(huì)被通過(guò)替換變成: fprintf(stderr,"Error!n",);很明顯,這里仍然會(huì)產(chǎn)生編譯錯(cuò)誤(非本例的某些情況下不會(huì)產(chǎn)生編譯錯(cuò)誤)。除了這種方式外,c99和GNU CPP都支持下面的宏定義方式: #define myprintf(templt, .) fprintf(stderr,templt, #_VAR_ARGS_)這時(shí),#這個(gè)連接符號(hào)充當(dāng)?shù)淖饔镁褪钱?dāng)_VAR_ARGS_為空的時(shí)候,消除前面的那個(gè)逗號(hào)。那么此時(shí)的翻譯過(guò)程如下: myprintf(
20、templt);被轉(zhuǎn)化為:fprintf(stderr,templt);這樣如果templt合法,將不會(huì)產(chǎn)生編譯錯(cuò)誤。 宏是如何解釋的 宏在日常編程中的常見(jiàn)使用 宏使用中的陷阱 這里列出了一些宏使用中容易出錯(cuò)的地方,以及合適的使用方式。 錯(cuò)誤的嵌套Misnesting宏的定義不一定要有完整的、配對(duì)的括號(hào),但是為了避免出錯(cuò)并且提高可讀性,最好避免這樣使用。 由操作符優(yōu)先級(jí)引起的問(wèn)題Operator Precedence Problem由于宏只是簡(jiǎn)單的替換,宏的參數(shù)如果是復(fù)合結(jié)構(gòu),那么通過(guò)替換之后可能由于各個(gè)參數(shù)之間的操作符優(yōu)先級(jí)高于單個(gè)參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級(jí),如果我們不用括號(hào)保
21、護(hù)各個(gè)宏參數(shù),可能會(huì)產(chǎn)生預(yù)想不到的情形。比如: #define ceil_div(x, y) (x + y - 1) / y那么 a = ceil_div( b & c, sizeof(int) );將被轉(zhuǎn)化為: a = ( b & c + sizeof(int) - 1) / sizeof(int);/ 由于+/-的優(yōu)先級(jí)高于&的優(yōu)先級(jí),那么上面式子等同于:a = ( b & (c + sizeof(int) - 1) / sizeof(int);這顯然不是調(diào)用者的初衷。為了避免這種情況發(fā)生,應(yīng)當(dāng)多寫(xiě)幾個(gè)括號(hào): define ceil_div(x, y) (x) + (y) - 1) / (y) 消除多余的分號(hào)Semicolon Swallowing通常情況下,為了使函數(shù)模樣的宏在表面上看起
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 鄉(xiāng)村振興戰(zhàn)略下職業(yè)技能培訓(xùn)對(duì)鄉(xiāng)村經(jīng)濟(jì)結(jié)構(gòu)調(diào)整的影響報(bào)告
- 808激光脫毛培訓(xùn)課件
- 中國(guó)衛(wèi)生監(jiān)督培訓(xùn)課件
- 員工安全操作課件
- 系文宣部培訓(xùn)大會(huì)
- 中國(guó)傳統(tǒng)節(jié)日課件背景
- 幼師教育案例分享
- 浙大中控培訓(xùn)
- 制作商務(wù)培訓(xùn)
- 企業(yè)法治教育培訓(xùn)
- 圖解“雙均線雙交叉”期貨、股票操作系統(tǒng)課件
- 小學(xué)語(yǔ)文擴(kuò)句、縮句專(zhuān)題
- 農(nóng)村公路安全生命防護(hù)工程施工方案
- (部編版)統(tǒng)編版小學(xué)語(yǔ)文教材目錄(一至六年級(jí)上冊(cè)下冊(cè)齊全)
- 抗滑樁專(zhuān)項(xiàng)的施工組織方案[專(zhuān)家評(píng)審]
- 常用彈簧鋼號(hào)對(duì)照表
- 應(yīng)用回歸分析(第三版)何曉群_劉文卿_課后習(xí)題答案_完整版
- 小學(xué)二年級(jí)下冊(cè)勞動(dòng)教案
- 食品安全及衛(wèi)生保證措施
- 60m3臥式液化石油氣儲(chǔ)罐設(shè)計(jì)
- 樹(shù)脂的污染及處理
評(píng)論
0/150
提交評(píng)論