青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

elva

C語言宏定義使用技巧

寫好C語言,漂亮的宏定義很重要,使用宏定義可以防止出錯(cuò),提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義。。。。。。
1,防止一個(gè)頭文件被重復(fù)包含

#ifndef COMDEF_H
#define COMDEF_H
//頭文件內(nèi)容
#endif
2,重新定義一些類型,防止由于各種平臺(tái)和編譯器的不同,而產(chǎn)生的類型字節(jié)數(shù)差異,方便移植。
typedef unsigned char boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned 32 bit value */
typedef 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; /* 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 long 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; /* Signed 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)中的偏移量
#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è)Word
#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
8,按照LSB格式把一個(gè)Word轉(zhuǎn)化為兩個(gè)字節(jié)
#define FLOPW( 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,返回一個(gè)比X大的最接近的8的倍數(shù)
#define RND8( x ) ((((x) + 7) / 8 ) * 8 )
12,將一個(gè)字母轉(zhuǎn)換為大寫
#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) >= '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) ) / sizeof( (a[0]) ) )
17,返回一個(gè)無符號(hào)數(shù)n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
#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 *)(port)))
#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)說明了五個(gè)預(yù)定義的宏名。它們是:
_ L I N E _
_ F I L E _
_ D A T E _
_ T I M E _
_ S T D C _
如果編譯不是標(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)的。
可以定義宏,例如:
當(dāng)定義了_DEBUG,輸出數(shù)據(jù)信息和所在文件所在行
#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
20,宏定義防止使用是錯(cuò)誤
用小括號(hào)包含。
例如:#define ADD(a,b) a+b
do{}while(0)語句包含多語句防止錯(cuò)誤
例如:#difne DO(a,b) a+b;\
a++;
應(yīng)用時(shí):if(.)
DO(a,b); //產(chǎn)生錯(cuò)誤
else


C語言中如何使用宏

C(和C++)中的宏(Macro)屬于編譯器預(yù)處理的范疇,屬于編譯期概念(而非運(yùn)行期概念)。下面對(duì)常遇到的宏的使用問題做了簡單總結(jié)。
宏使用中的常見的基礎(chǔ)問題
#符號(hào)和##符號(hào)的使用
...符號(hào)的使用
宏的解釋方法
我們能碰到的宏的使用
宏使用中的陷阱

常見的基礎(chǔ)性問題:


關(guān)于#和##
在C語言的宏中,#的功能是將其后面的宏參數(shù)進(jìn)行字符串化操作(Stringfication),簡單說就是在對(duì)它所引用的宏變量通過替換后在其左右各加上一個(gè)雙引號(hào)。比如下面代碼中的宏:
#define WARN_IF(EXP) \
do{ if (EXP) \
fprintf(stderr, "Warning: " #EXP "\n"); } \
while(0)
那么實(shí)際使用中會(huì)出現(xiàn)下面所示的替換過程:
WARN_IF (divider == 0);
被替換為
do {
if (divider == 0)
fprintf(stderr, "Warning" "divider == 0" "\n");
} while(0);
這樣每次divider(除數(shù))為0的時(shí)候便會(huì)在標(biāo)準(zhǔn)錯(cuò)誤流上輸出一個(gè)提示信息。
而## 被稱為連接符(concatenator),用來將兩個(gè)Token連接為一個(gè)Token。注意這里連接的對(duì)象是Token就行,而不一定是宏的變量。比如 你要做一個(gè)菜單項(xiàng)命令名和函數(shù)指針組成的結(jié)構(gòu)體的數(shù)組,并且希望在函數(shù)名和菜單項(xiàng)命令名之間有直觀的、名字上的關(guān)系。那么下面的代碼就非常實(shí)用:
struct command
{
char * name;
void (*function) (void);
};
#define COMMAND(NAME) { NAME, NAME ## _command }
// 然后你就用一些預(yù)先定義好的命令來方便的初始化一個(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,d) a##_##b##_##c##_##d
typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
// 這里這個(gè)語句將展開為:
// typedef struct _record_type name_company_position_salary;

關(guān)于...的使用
...在C宏中稱為Variadic Macro,也就是變參宏。比如:
#define myprintf(templt,...) fprintf(stderr,templt,__VA_ARGS__)
// 或者
#define myprintf(templt,args...) fprintf(stderr,templt,args)
第一個(gè)宏中由于沒有對(duì)變參起名,我們用默認(rèn)的宏__VA_ARGS__來替代它。第二個(gè)宏中,我們顯式地命名變參為args,那么我們?cè)诤甓x中就可以用 args來代指變參了。同C語言的stdcall一樣,變參必須作為參數(shù)表的最有一項(xiàng)出現(xiàn)。當(dāng)上面的宏中我們只能提供第一個(gè)參數(shù)templt時(shí),C標(biāo)準(zhǔn)要 求我們必須寫成:
myprintf(templt,);
的形式。這時(shí)的替換過程為:
myprintf("Error!\n",);
替換為:
fprintf(stderr,"Error!\n",);
這是一個(gè)語法錯(cuò)誤,不能正常編譯。這個(gè)問題一般有兩個(gè)解決方法。首先,GNU CPP提供的解決方法允許上面的宏調(diào)用寫成:
myprintf(templt);
而它將會(huì)被通過替換變成:
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í)的翻譯過程如下:
myprintf(templt);
被轉(zhuǎn)化為:
fprintf(stderr,templt);
這樣如果templt合法,將不會(huì)產(chǎn)生編譯錯(cuò)誤。
宏是如何解釋的
宏在日常編程中的常見使用
宏使用中的陷阱
這里列出了一些宏使用中容易出錯(cuò)的地方,以及合適的使用方式。
錯(cuò)誤的嵌套-Misnesting
宏的定義不一定要有完整的、配對(duì)的括號(hào),但是為了避免出錯(cuò)并且提高可讀性,最好避免這樣使用。
由操作符優(yōu)先級(jí)引起的問題-Operator Precedence Problem
由于宏只是簡單的替換,宏的參數(shù)如果是復(fù)合結(jié)構(gòu),那么通過替換之后可能由于各個(gè)參數(shù)之間的操作符優(yōu)先級(jí)高于單個(gè)參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級(jí),如果我們不用括號(hào)保護(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)多寫幾個(gè)括號(hào):
define ceil_div(x, y) (((x) + (y) - 1) / (y))
消除多余的分號(hào)-Semicolon Swallowing
通常情況下,為了使函數(shù)模樣的宏在表面上看起來像一個(gè)通常的C語言調(diào)用一樣,通常情況下我們?cè)诤甑暮竺婕由弦粋€(gè)分號(hào),比如下面的帶參宏:
MY_MACRO(x);
但是如果是下面的情況:
#define MY_MACRO(x) { \
/* line 1 */ \
/* line 2 */ \
/* line 3 */ }
//...
if (condition())
MY_MACRO(a);
else
{...}
這樣會(huì)由于多出的那個(gè)分號(hào)產(chǎn)生編譯錯(cuò)誤。為了避免這種情況出現(xiàn)同時(shí)保持MY_MACRO(x);的這種寫法,我們需要把宏定義為這種形式:
#define MY_MACRO(x) do {
/* line 1 */ \
/* line 2 */ \
/* line 3 */ } while(0)
這樣只要保證總是使用分號(hào),就不會(huì)有任何問題。
Duplication of Side Effects
這里的Side Effect是指宏在展開的時(shí)候?qū)ζ鋮?shù)可能進(jìn)行多次Evaluation(也就是取值),但是如果這個(gè)宏參數(shù)是一個(gè)函數(shù),那么就有可能被調(diào)用多次從而達(dá)到不一致的結(jié)果,甚至?xí)l(fā)生更嚴(yán)重的錯(cuò)誤。比如:
#define min(X,Y) ((X) > (Y) ? (Y) : (X))
//...
c = min(a,foo(b));
這時(shí)foo()函數(shù)就被調(diào)用了兩次。為了解決這個(gè)潛在的問題,我們應(yīng)當(dāng)這樣寫min(X,Y)這個(gè)宏:
#define min(X,Y) ({ \
typeof (X) x_ = (X); \
typeof (Y) y_ = (Y); \
(x_ < y_) ? x_ : y_; })
({...})的作用是將內(nèi)部的幾條語句中最后一條的值返回,它也允許在內(nèi)部聲明變量(因?yàn)樗ㄟ^大括號(hào)組成了一個(gè)局部Scope)。

posted on 2008-08-11 15:13 葉子 閱讀(2624) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C\C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            午夜在线观看免费一区| 欧美成人午夜影院| 久久久99免费视频| 国产精品国产三级国产| 久久在线91| 欧美xx视频| 欧美一区二区视频观看视频| 欧美自拍偷拍| 午夜精品福利一区二区蜜股av| 一色屋精品亚洲香蕉网站| 国产精品久久久久久久久免费桃花 | 亚洲第一二三四五区| 欧美日韩国产在线播放网站| 国产亚洲精品久久久久久| 亚洲免费精品| 国产精品白丝jk黑袜喷水| 中国女人久久久| 亚洲日本视频| 欧美福利影院| 欧美激情小视频| 亚洲电影激情视频网站| 久久久综合网站| 国产欧美日韩一区| 老司机成人在线视频| 女女同性精品视频| 欧美成人免费全部| 国产精品资源| 国产亚洲精品v| 99在线精品视频在线观看| 欧美日韩国产综合久久| 欧美精品一区在线| 国产在线精品成人一区二区三区 | 国产日韩欧美精品在线| 老司机精品导航| 午夜影院日韩| 亚洲欧美在线观看| 黄页网站一区| 欧美一区午夜视频在线观看| 亚洲第一福利社区| 亚洲综合三区| 在线色欧美三级视频| 欧美激情第10页| 亚洲国产福利在线| 99视频超级精品| 国内精品嫩模av私拍在线观看| 欧美精品成人91久久久久久久| 久久久久久久综合| 欧美在线视频导航| 亚洲欧美成人在线| 亚洲一区一卡| 亚洲一区二区三区激情| 一本色道久久综合精品竹菊| 亚洲毛片在线| 亚洲你懂的在线视频| 一本色道久久加勒比精品| 亚洲青色在线| 亚洲天堂网在线观看| 亚洲在线不卡| 久久午夜电影网| 欧美激情一区二区三区在线视频观看 | 欧美日韩精品在线视频| 亚洲一区免费在线观看| 在线成人黄色| 麻豆精品视频在线观看| 亚洲国产精品一区二区www| 亚洲免费视频网站| 亚洲精品乱码| 亚洲欧洲日产国产网站| 亚洲激情亚洲| 黄色成人在线| 99re66热这里只有精品3直播| 亚洲午夜av电影| 亚洲午夜高清视频| 欧美成人69av| 国产综合亚洲精品一区二| 欧美视频官网| 一区二区精品在线观看| 一区二区三区免费观看| 亚洲精品网址在线观看| 久久一区精品| 久热精品视频在线观看一区| 欧美黄色免费网站| 午夜视频久久久| 亚洲视频播放| 亚洲视频一区二区在线观看 | 国产色综合天天综合网| 欧美影院在线| 一区二区三区在线视频观看 | 在线成人av.com| 欧美风情在线观看| 91久久综合亚洲鲁鲁五月天| 欧美一区二区视频在线| 玖玖在线精品| 欧美视频一区在线| 亚洲国产精品久久久久秋霞蜜臀| 亚洲电影av在线| aa国产精品| 国产精品九九| 欧美1区2区| 另类专区欧美制服同性| 久久人人爽人人爽| 亚洲午夜精品视频| 99视频精品全部免费在线| 久久精品视频在线看| 久久久999精品免费| 国产欧美一区二区三区在线老狼 | 国产久一道中文一区| 久久一区精品| 欧美亚洲午夜视频在线观看| 老司机精品久久| 久久国产精品99国产精| 欧美成人免费视频| 又紧又大又爽精品一区二区| 影音先锋久久| 一区二区精品在线观看| 国产精品久久久久天堂| 亚洲欧美一区二区三区极速播放| 免费高清在线一区| 亚洲三级免费观看| 一区在线影院| 亚洲日韩视频| 樱桃国产成人精品视频| 国产精品剧情在线亚洲| 欧美成人小视频| 国产精品www色诱视频| 国产精品福利在线观看网址| 性做久久久久久久免费看| 国产精品99久久久久久www| 国产精品v亚洲精品v日韩精品| 国产精品99久久不卡二区 | 国产精品羞羞答答xxdd| 亚洲视频第一页| 欧美精品三区| 另类春色校园亚洲| 国产精品丝袜91| 亚洲精品国产精品乱码不99| 国产一区久久| 一本色道久久88精品综合| 亚洲第一成人在线| 香蕉精品999视频一区二区| 在线观看日韩av电影| 亚洲一卡久久| 老司机午夜精品视频| 久久久午夜电影| 久久国产精品72免费观看| 国产色视频一区| 日韩视频一区二区在线观看| 亚洲国产精品一区在线观看不卡 | 亚洲狠狠丁香婷婷综合久久久| 亚洲精品乱码久久久久久蜜桃91 | 亚洲午夜羞羞片| 日韩天天综合| 免费观看一区| 美女91精品| 一区二区在线观看视频| 亚洲欧美日本日韩| 性欧美xxxx视频在线观看| 午夜伦理片一区| 欧美一区二区三区四区高清| 欧美黄色影院| 亚洲大片在线| 亚洲国产日韩一区| 久久综合九色综合久99| 噜噜噜噜噜久久久久久91| 国户精品久久久久久久久久久不卡| 久久精品女人的天堂av| 在线免费高清一区二区三区| 欧美破处大片在线视频| 亚洲影院免费观看| 欧美巨乳在线观看| 91久久精品www人人做人人爽| 激情久久五月| 亚洲欧美日韩一区二区| 亚洲精品日产精品乱码不卡| 欧美+亚洲+精品+三区| 亚洲黄色影片| 亚洲一区二区欧美| 国产欧美欧美| 久久久噜噜噜久噜久久| 亚洲高清在线| 亚洲天堂久久| 国产日韩综合一区二区性色av| 久久激情五月婷婷| 欧美高清在线观看| 一本色道久久综合亚洲二区三区| 欧美极品aⅴ影院| 亚洲午夜久久久久久久久电影院 | 欧美影院久久久| 激情久久一区| 欧美成人精品在线| 香蕉久久夜色精品| 亚洲国产精品久久久久秋霞影院| 亚洲欧美精品一区| 一区视频在线看| 午夜免费电影一区在线观看| 欧美jizzhd精品欧美喷水| 亚洲国产第一| 欧美中文在线字幕| 在线看国产一区| 国产日韩欧美视频|