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

elva

C語言宏定義使用技巧

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

#ifndef COMDEF_H
#define COMDEF_H
//頭文件內容
#endif
2,重新定義一些類型,防止由于各種平臺和編譯器的不同,而產生的類型字節數差異,方便移植。
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,得到指定地址上的一個字節或字
#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,得到一個field在結構體(struct)中的偏移量
#define FPOS( type, field ) \
/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
6,得到一個結構體中field所占用的字節數
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
7,按照LSB格式把兩個字節轉化為一個Word
#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
8,按照LSB格式把一個Word轉化為兩個字節
#define FLOPW( ray, val ) \
(ray)[0] = ((val) / 256); \
(ray)[1] = ((val) & 0xFF)
9,得到一個變量的地址(word寬度)
#define B_PTR( var ) ( (byte *) (void *) &(var) )
#define W_PTR( var ) ( (word *) (void *) &(var) )
10,得到一個字的高位和低位字節
#define WORD_LO(***) ((byte) ((word)(***) & 255))
#define WORD_HI(***) ((byte) ((word)(***) >> 8))
11,返回一個比X大的最接近的8的倍數
#define RND8( x ) ((((x) + 7) / 8 ) * 8 )
12,將一個字母轉換為大寫
#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )
13,判斷字符是不是10進值的數字
#define DECCHK( c ) ((c) >= '0' && (c) <= '9')
14,判斷字符是不是16進值的數字
#define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9') ||\
((c) >= 'A' && (c) <= 'F') ||\
((c) >= 'a' && (c) <= 'f') )
15,防止溢出的一個方法
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
16,返回數組元素的個數
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
17,返回一個無符號數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,對于IO空間映射在存儲空間的結構,輸入輸出處理
#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,使用一些宏跟蹤調試
A N S I標準說明了五個預定義的宏名。它們是:
_ L I N E _
_ F I L E _
_ D A T E _
_ T I M E _
_ S T D C _
如果編譯不是標準的,則可能僅支持以上宏名中的幾個,或根本不支持。記住編譯程序
也許還提供其它預定義的宏名。
_ L I N E __ F I L E _宏指令在有關# l i n e的部分中已討論,這里討論其余的宏名。
_ D AT E _宏指令含有形式為月//年的串,表示源文件被翻譯到代碼時的日期。
源代碼翻譯到目標代碼的時間作為串包含在_ T I M E _中。串形式為時:分:秒。
如果實現是標準的,則宏_ S T D C _含有十進制常量1。如果它含有任何其它數,則實現是
非標準的。
可以定義宏,例如:
當定義了_DEBUG,輸出數據信息和所在文件所在行
#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
20,宏定義防止使用是錯誤
用小括號包含。
例如:#define ADD(a,b) a+b
do{}while(0)語句包含多語句防止錯誤
例如:#difne DO(a,b) a+b;\
a++;
應用時:if(.)
DO(a,b); //產生錯誤
else


C語言中如何使用宏

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

常見的基礎性問題:


關于#和##
在C語言的宏中,#的功能是將其后面的宏參數進行字符串化操作(Stringfication),簡單說就是在對它所引用的宏變量通過替換后在其左右各加上一個雙引號。比如下面代碼中的宏:
#define WARN_IF(EXP) \
do{ if (EXP) \
fprintf(stderr, "Warning: " #EXP "\n"); } \
while(0)
那么實際使用中會出現下面所示的替換過程:
WARN_IF (divider == 0);
被替換為
do {
if (divider == 0)
fprintf(stderr, "Warning" "divider == 0" "\n");
} while(0);
這樣每次divider(除數)為0的時候便會在標準錯誤流上輸出一個提示信息。
而## 被稱為連接符(concatenator),用來將兩個Token連接為一個Token。注意這里連接的對象是Token就行,而不一定是宏的變量。比如 你要做一個菜單項命令名和函數指針組成的結構體的數組,并且希望在函數名和菜單項命令名之間有直觀的、名字上的關系。那么下面的代碼就非常實用:
struct command
{
char * name;
void (*function) (void);
};
#define COMMAND(NAME) { NAME, NAME ## _command }
// 然后你就用一些預先定義好的命令來方便的初始化一個command結構的數組了:
struct command commands[] = {
COMMAND(quit),
COMMAND(help),
...
}
COMMAND宏在這里充當一個代碼生成器的作用,這樣可以在一定程度上減少代碼密度,間接地也可以減少不留心所造成的錯誤。我們還可以n個##符號連接 n+1個Token,這個特性也是#符號所不具備的。比如:
#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d
typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
// 這里這個語句將展開為:
// typedef struct _record_type name_company_position_salary;

關于...的使用
...在C宏中稱為Variadic Macro,也就是變參宏。比如:
#define myprintf(templt,...) fprintf(stderr,templt,__VA_ARGS__)
// 或者
#define myprintf(templt,args...) fprintf(stderr,templt,args)
第一個宏中由于沒有對變參起名,我們用默認的宏__VA_ARGS__來替代它。第二個宏中,我們顯式地命名變參為args,那么我們在宏定義中就可以用 args來代指變參了。同C語言的stdcall一樣,變參必須作為參數表的最有一項出現。當上面的宏中我們只能提供第一個參數templt時,C標準要 求我們必須寫成:
myprintf(templt,);
的形式。這時的替換過程為:
myprintf("Error!\n",);
替換為:
fprintf(stderr,"Error!\n",);
這是一個語法錯誤,不能正常編譯。這個問題一般有兩個解決方法。首先,GNU CPP提供的解決方法允許上面的宏調用寫成:
myprintf(templt);
而它將會被通過替換變成:
fprintf(stderr,"Error!\n",);
很明顯,這里仍然會產生編譯錯誤(非本例的某些情況下不會產生編譯錯誤)。除了這種方式外,c99和GNU CPP都支持下面的宏定義方式:
#define myprintf(templt, ...) fprintf(stderr,templt, ##__VAR_ARGS__)
這時,##這個連接符號充當的作用就是當__VAR_ARGS__為空的時候,消除前面的那個逗號。那么此時的翻譯過程如下:
myprintf(templt);
被轉化為:
fprintf(stderr,templt);
這樣如果templt合法,將不會產生編譯錯誤。
宏是如何解釋的
宏在日常編程中的常見使用
宏使用中的陷阱
這里列出了一些宏使用中容易出錯的地方,以及合適的使用方式。
錯誤的嵌套-Misnesting
宏的定義不一定要有完整的、配對的括號,但是為了避免出錯并且提高可讀性,最好避免這樣使用。
由操作符優先級引起的問題-Operator Precedence Problem
由于宏只是簡單的替換,宏的參數如果是復合結構,那么通過替換之后可能由于各個參數之間的操作符優先級高于單個參數內部各部分之間相互作用的操作符優先級,如果我們不用括號保護各個宏參數,可能會產生預想不到的情形。比如:
#define ceil_div(x, y) (x + y - 1) / y
那么
a = ceil_div( b & c, sizeof(int) );
將被轉化為:
a = ( b & c + sizeof(int) - 1) / sizeof(int);
// 由于+/-的優先級高于&的優先級,那么上面式子等同于:
a = ( b & (c + sizeof(int) - 1)) / sizeof(int);
這顯然不是調用者的初衷。為了避免這種情況發生,應當多寫幾個括號:
define ceil_div(x, y) (((x) + (y) - 1) / (y))
消除多余的分號-Semicolon Swallowing
通常情況下,為了使函數模樣的宏在表面上看起來像一個通常的C語言調用一樣,通常情況下我們在宏的后面加上一個分號,比如下面的帶參宏:
MY_MACRO(x);
但是如果是下面的情況:
#define MY_MACRO(x) { \
/* line 1 */ \
/* line 2 */ \
/* line 3 */ }
//...
if (condition())
MY_MACRO(a);
else
{...}
這樣會由于多出的那個分號產生編譯錯誤。為了避免這種情況出現同時保持MY_MACRO(x);的這種寫法,我們需要把宏定義為這種形式:
#define MY_MACRO(x) do {
/* line 1 */ \
/* line 2 */ \
/* line 3 */ } while(0)
這樣只要保證總是使用分號,就不會有任何問題。
Duplication of Side Effects
這里的Side Effect是指宏在展開的時候對其參數可能進行多次Evaluation(也就是取值),但是如果這個宏參數是一個函數,那么就有可能被調用多次從而達到不一致的結果,甚至會發生更嚴重的錯誤。比如:
#define min(X,Y) ((X) > (Y) ? (Y) : (X))
//...
c = min(a,foo(b));
這時foo()函數就被調用了兩次。為了解決這個潛在的問題,我們應當這樣寫min(X,Y)這個宏:
#define min(X,Y) ({ \
typeof (X) x_ = (X); \
typeof (Y) y_ = (Y); \
(x_ < y_) ? x_ : y_; })
({...})的作用是將內部的幾條語句中最后一條的值返回,它也允許在內部聲明變量(因為它通過大括號組成了一個局部Scope)。

posted on 2008-08-11 15:13 葉子 閱讀(2624) 評論(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>
            一色屋精品视频在线观看网站| 久久精品九九| 久久久久久久波多野高潮日日| 亚洲一区二区视频在线| 亚洲免费中文字幕| 欧美一区二区三区四区在线 | 中文网丁香综合网| 欧美中文字幕在线播放| 欧美一区二区三区在线视频| 亚洲乱码国产乱码精品精| 激情欧美一区| 在线观看91精品国产入口| 国内精品久久久久影院薰衣草| 国产日韩三区| 欧美手机在线视频| 欧美精品亚洲一区二区在线播放| 欧美日韩国产影片| 欧美日韩专区在线| 激情欧美日韩一区| 亚洲国产精品国自产拍av秋霞| 亚洲理论在线观看| 亚洲视频在线视频| 亚洲欧美成aⅴ人在线观看| 久久精品99久久香蕉国产色戒 | 欧美另类一区| 国产亚洲欧洲一区高清在线观看| 国产精品99久久久久久久久| 亚洲视频自拍偷拍| 亚洲狼人精品一区二区三区| 先锋a资源在线看亚洲| 性色av一区二区三区在线观看 | 亚洲欧美中日韩| 蜜臀av一级做a爰片久久| 免费成人网www| 欧美日韩一区三区| 欧美午夜电影在线观看| 欧美一区日本一区韩国一区| 久久久久高清| 欧美成人一区二区三区在线观看| 国产欧美日韩视频| 亚洲国产精品va在线看黑人| 久久国产福利| 亚洲国产另类久久久精品极度| 亚洲国产精品一区制服丝袜| 欧美一区二区三区在线看| 久久亚洲影院| 国产偷国产偷精品高清尤物| 亚洲美女在线看| 99riav国产精品| 亚洲国产精品久久91精品| 亚洲无人区一区| 久久欧美中文字幕| 中文在线一区| 欧美99久久| 国产一区二区三区四区五区美女| 在线看视频不卡| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 国产午夜精品久久久| 国产一区二区三区久久久久久久久 | 国产乱码精品一区二区三区五月婷 | 日韩一本二本av| 午夜激情综合网| 久久激情一区| 欧美中文字幕不卡| 欧美婷婷久久| 亚洲专区一二三| 91久久久久久| 欧美日韩国产精品一区| 亚洲精品在线电影| 亚洲精品国精品久久99热一| 欧美日韩日本视频| 国产精品欧美在线| 午夜日韩在线观看| 亚洲精品无人区| 欧美一区二区| 国产乱码精品一区二区三区av| 一区二区三区四区五区精品| 日韩一级黄色av| 欧美日本精品一区二区三区| 亚洲手机视频| 99在线精品视频在线观看| 亚洲视频在线一区观看| 国产精品日韩精品欧美在线| 亚洲在线一区二区| 香蕉乱码成人久久天堂爱免费| 欧美四级在线观看| 性色av一区二区三区| 99pao成人国产永久免费视频| 猛男gaygay欧美视频| 夜夜嗨一区二区三区| 亚洲精品欧美专区| 国产欧美日韩专区发布| 久久久精品日韩| 亚洲精品一区二区三区四区高清 | 欧美日韩国产综合视频在线| 一区二区三区在线观看国产| 亚洲福利视频专区| 欧美福利一区二区三区| 国产精品日韩高清| 久久综合精品国产一区二区三区| 久久精品二区亚洲w码| 亚洲精品偷拍| 9色精品在线| 禁断一区二区三区在线| 欧美肥婆bbw| 欧美在线免费观看视频| 亚洲精品久久久一区二区三区| 91久久久久| 国产人成精品一区二区三| 麻豆免费精品视频| 欧美另类人妖| 亚洲国产第一页| 国产精品乱码| 亚洲精品免费电影| 国产亚洲激情在线| 亚洲男人天堂2024| 极品尤物av久久免费看 | 亚洲缚视频在线观看| 欧美日本精品| 久久久久久久国产| 欧美日韩一区二区三| 久久激情视频免费观看| 欧美成人资源网| 国产噜噜噜噜噜久久久久久久久 | 久久精品综合| 一区二区三区四区蜜桃| 欧美一区免费| 久久网站热最新地址| 欧美日韩一级视频| 日韩视频在线免费| 亚洲国产成人精品久久久国产成人一区| 午夜精品久久久久久99热软件 | 欧美人成网站| 久久精品人人爽| 国产一区二区精品丝袜| 99国内精品久久| 亚洲视频高清| 欧美成人日韩| 亚洲片国产一区一级在线观看| 激情久久久久久久久久久久久久久久| 欧美激情中文字幕在线| 亚洲电影免费观看高清完整版在线观看 | 欧美国产日韩一区| 久久免费一区| 亚洲视频狠狠| 亚洲影院免费观看| 欧美紧缚bdsm在线视频| 99热精品在线观看| 亚洲视频观看| 欧美大片在线观看| 亚洲欧洲精品一区二区三区波多野1战4| 国产欧美亚洲日本| 久久精品国产2020观看福利| 欧美一区二区三区免费看| 国产精品网站视频| 亚洲综合首页| 欧美成人久久| 最新精品在线| 久久精品国产999大香线蕉| 国产日韩欧美综合精品| 欧美一级二区| 久久一区亚洲| 在线免费不卡视频| 国产精品久久久久久久久久尿| 日韩西西人体444www| 欧美一区网站| 国产欧美一区二区精品仙草咪| 久久久国产午夜精品| 久久综合给合久久狠狠狠97色69| 亚洲国产精品一区二区第一页 | 亚洲第一精品影视| 欧美日韩亚洲一区二区| 最新成人在线| 欧美一级片久久久久久久| 国产丝袜美腿一区二区三区| 亚洲片国产一区一级在线观看| 欧美一区永久视频免费观看| 国产精品自拍三区| 欧美激情精品久久久久久免费印度 | 亚洲黄色小视频| 国产精品久久久99| 欧美自拍偷拍| 一本一本久久a久久精品综合妖精| 亚洲一区亚洲| 国产精品久久久久婷婷| 嫩草成人www欧美| 亚洲欧洲精品一区二区三区 | 性欧美在线看片a免费观看| 国产区二精品视| 欧美日韩免费网站| 久久av免费一区| 久久精品视频导航| 亚洲免费视频网站| 黄色成人免费观看| 国产精自产拍久久久久久| 久久综合九色欧美综合狠狠| 午夜欧美精品久久久久久久| 欧美激情一区二区三区在线视频 | 久久最新视频| 亚洲乱码久久|