LALA  
          日歷
          <2008年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導(dǎo)航

          留言簿(1)

          隨筆分類(31)

          文章分類(4)

          收藏夾(21)

          搜索

          •  

          積分與排名

          • 積分 - 29910
          • 排名 - 1389

          最新隨筆

          最新評論

          閱讀排行榜

           
          C語言宏定義技巧(常用宏定義) 
           
          寫好C語言,漂亮的宏定義很重要,使用宏定義可以防止出錯,提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得宏定義。。。。。。

           

          1,防止一個頭文件被重復(fù)包含

          #ifndef COMDEF_H

          #define COMDEF_H

            //頭文件內(nèi)容

          #endif

          2,重新定義一些類型,防止由于各種平臺和編譯器的不同,而產(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,得到指定地址上的一個字節(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,得到一個field在結(jié)構(gòu)體(struct)中的偏移量

          #define FPOS( type, field ) \

          /*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */

          6,得到一個結(jié)構(gòu)體中field所占用的字節(jié)數(shù)

          #define FSIZ( type, field ) sizeof( ((type *) 0)->field )

          7,按照LSB格式把兩個字節(jié)轉(zhuǎn)化為一個Word

          #define  FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )

          8,按照LSB格式把一個Word轉(zhuǎn)化為兩個字節(jié)

          #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,得到一個字的高位和低位字節(jié)

          #define  WORD_LO(xxx)  ((byte) ((word)(xxx) & 255))

          #define  WORD_HI(xxx)  ((byte) ((word)(xxx) >> 8))

          11,返回一個比X大的最接近的8的倍數(shù)

          #define RND8( x )       ((((x) + 7) / 8 ) * 8 )

          12,將一個字母轉(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,防止溢出的一個方法

          #define  INC_SAT( val )  (val = ((val)+1 > (val)) ? (val)+1 : (val))

          16,返回數(shù)組元素的個數(shù)

          #define  ARR_SIZE( a )  ( sizeof( (a) ) / sizeof( (a[0]) ) )

          17,返回一個無符號數(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,對于IO空間映射在存儲空間的結(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)說明了五個預(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)的,則可能僅支持以上宏名中的幾個,或根本不支持。記住編譯程序

          也許還提供其它預(yù)定義的宏名。

          _ L I N E _及_ F I L E _宏指令在有關(guān)# l i n e的部分中已討論,這里討論其余的宏名。

          _ D AT E _宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。

          源代碼翻譯到目標(biāo)代碼的時間作為串包含在_ T I M E _中。串形式為時:分:秒。

          如果實現(xiàn)是標(biāo)準(zhǔn)的,則宏_ S T D C _含有十進(jìn)制常量1。如果它含有任何其它數(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,宏定義防止使用是錯誤

          用小括號包含。

          例如:#define ADD(a,b) (a+b)

          用do{}while(0)語句包含多語句防止錯誤

          例如:#difne DO(a,b) a+b;\

                             a++;

          應(yīng)用時:if(….)

                    DO(a,b); //產(chǎn)生錯誤

                  else

                  

          解決方法: #difne DO(a,b) do{a+b;\

                             a++;}while(0) 

           
          宏中"#"和"##"的用法
          一、一般用法
          我們使用#把宏參數(shù)變?yōu)橐粋€字符串,用##把兩個宏參數(shù)貼合在一起.
          用法:
          #i nclude<cstdio>
          #i nclude<climits>
          using namespace std;

          #define STR(s)     #s
          #define CONS(a,b)  int(a##e##b)

          int main()
          {
              printf(STR(vck));           // 輸出字符串"vck"
              printf("%d\n", CONS(2,3));  // 2e3 輸出:2000
              return 0;
          }

          二、當(dāng)宏參數(shù)是另一個宏的時候
          需要注意的是凡宏定義里有用'#'或'##'的地方宏參數(shù)是不會再展開.

          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里的參數(shù)TOW會被展開為(2).

          2, 當(dāng)有'#'或'##'的時候
          #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<climits>
          這行會被展開為:
          printf("int max: %s\n", "INT_MAX");

          printf("%s\n", CONS(A, A));               // compile error 
          這一行則是:
          printf("%s\n", int(AeA));

          INT_MAX和A都不會再被展開, 然而解決這個問題的方法很簡單. 加多一層中間轉(zhuǎn)換宏.
          加這層宏的用意是把所有宏的參數(shù)在這層里全部展開, 那么在轉(zhuǎn)換宏里的那一個宏(_STR)就能得到正確的宏參數(shù).

          #define A           (2)
          #define _STR(s)     #s
          #define STR(s)      _STR(s)          // 轉(zhuǎn)換宏
          #define _CONS(a,b)  int(a##e##b)
          #define CONS(a,b)   _CONS(a,b)       // 轉(zhuǎn)換宏

          printf("int max: %s\n", STR(INT_MAX));          // INT_MAX,int型的最大值,為一個變量 #i nclude<climits>
          輸出為: int max: 0x7fffffff
          STR(INT_MAX) -->  _STR(0x7fffffff) 然后再轉(zhuǎn)換成字符串;

          printf("%d\n", CONS(A, A));
          輸出為:200
          CONS(A, A)  -->  _CONS((2), (2))  --> int((2)e(2))

          三、'#'和'##'的一些應(yīng)用特例
          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;
          即每次只能解開當(dāng)前層的宏,所以__LINE__在第二層才能被解開;

          2、填充結(jié)構(gòu)
          #define  FILL(a)   {a, #a}

          enum IDD{OPEN, CLOSE};
          typedef struct MSG{
            IDD id;
            const char * msg;
          }MSG;

          MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
          相當(dāng)于:
          MSG _msg[] = {{OPEN, "OPEN"},
                        {CLOSE, "CLOSE"}};

          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、得到一個數(shù)值類型所對應(yīng)的字符串緩沖大小
          #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"];
          這里相當(dāng)于:
          posted on 2008-09-23 09:11 Dest 閱讀(247) 評論(0)  編輯  收藏 所屬分類: C語言
           
          Copyright © Dest Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 招远市| 孝感市| 成都市| 贵港市| 海伦市| 新乡县| 永泰县| 高淳县| 青冈县| 桃园市| 桐梓县| 佛教| 澄江县| 郸城县| 于田县| 团风县| 山阴县| 弥渡县| 延安市| 西丰县| 鄂州市| 兴国县| 龙口市| 沾化县| 锦屏县| 华蓥市| 吴忠市| 怀仁县| 武山县| 满洲里市| 嘉定区| 湖州市| 固安县| 白河县| 芦溪县| 鄂伦春自治旗| 武城县| 通化县| 丁青县| 嘉荫县| 习水县|