zoukankan      html  css  js  c++  java
  • [转载]C宏定义的小结

    FROM:http://blog.csdn.net/sunboy_2050/article/details/6103530

    实现代码实例

    程序代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    
    /***** cplusplus *****/
    #if 0
    #include <iostream>  
    using namespace std;
    #endif
    
    // 得到指定地址上的一个字节或字
    #define MEM_B(x) (*((byte *)(x)))  
    #define MEM_W(x) (*((word *)(x)))
    
    // 得到一个field在结构体(struct)中的偏移量
    #define FPOS(type, field) ((dword)&((type *)0)->field)
    
    // 将一个字母字符转换为大写
    #define UPCASE(c) (((c)>='a' && (c)<='z') ? ((c)-0x20) : (c))
    
    // 判断字符是否为十进制的数字
    #define DECCHECK(c) ((c)>='0' && (c)<='9')
    
    // 判断字符是否为十六进制的数字
    #define HEXCHECK(hex) (((hex)>='0' && (hex)<='9')||((hex)>='A' && (hex)<='F')||((hex)>='a' && (hex)<='f'))                                                          
    // 防止溢出的一个方法
    #define INC_SAT(val) (val=((val)+1 > (val)) ? (val)+1 : (val))
                                      
    // 计算数组元素的个数
    #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
                                                              
    int
    main(void)
    {
        int x = 0x1234abcd;
        char c = 'a';
        char dec = '5';
        char hex = 'e';
        char array[10] = {'1'};
    
        //printf("MEM_B(x): 0x%p/n", MEM_B(x));
        //printf("MEM_W(x): 0x%p/n", MEM_W(x));
    
        printf("UPCASE(c): %c -> %c/n", c, UPCASE(c));
        printf("DECCHECK(dec): %c -> %d/n", dec, DECCHECK(dec));
        printf("HEXCHECK(hex): %c -> %d/n", hex, HEXCHECK(hex));
        printf("ARRAY_SIZE(array): array[10] -> %d/n", ARRAY_SIZE(array));
    
        printf("/n/****** MACRO ******//n");
        printf("__LINE__: %d/n", __LINE__);
        printf("__FILE__: %s/n", __FILE__);
        printf("__DATE__: %s/n", __DATE__);
        printf("__TIME__: %s/n", __TIME__);
        printf("__func__: %s/n", __func__);
    #ifdef __cplusplus
        cout <<"hello __cplusplus"<<endl;
    #endif
    #ifdef __STDC__
        printf("hello __STDC__/n");
    #endif
        
        printf("/n/****** sizeof() ******//n");
        //printf("sizeof(byte): %d/n", sizeof(byte));
        printf("sizeof(char): %d/n", sizeof(char));
        printf("sizeof(signed char): %d/n", sizeof(signed char));
        printf("sizeof(unsigned char): %d/n", sizeof(unsigned char));
        printf("sizeof(short): %d/n", sizeof(short));
        printf("sizeof(signed short): %d/n", sizeof(signed short));
        printf("sizeof(unsigned short): %d/n", sizeof(unsigned short));
        printf("sizeof(int): %d/n", sizeof(int));
        printf("sizeof(signed int): %d/n", sizeof(signed int));
        printf("sizeof(unsigned int): %d/n", sizeof(unsigned int));
        printf("sizeof(long): %d/n", sizeof(long));
        printf("sizeof(signed long): %d/n", sizeof(signed long));
        printf("sizeof(unsigned long): %d/n", sizeof(unsigned long));
        printf("sizeof(long long): %d/n", sizeof(long long));
        printf("sizeof(signed long long): %d/n", sizeof(signed long long));
        printf("sizeof(unsigned long long): %d/n", sizeof(unsigned long long));
        printf("sizeof(float): %d/n", sizeof(float));
        printf("sizeof(double): %d/n", sizeof(double));
        
        
        exit(EXIT_SUCCESS);
    }
    
    
    
    运行结果:
    [work@db-testing-com06-vm3.db01.baidu.com c++]$ gcc -W -o micro micro.c 
    [work@db-testing-com06-vm3.db01.baidu.com c++]$ ./micro    
    UPCASE(c): a -> A
    DECCHECK(dec): 5 -> 1
    HEXCHECK(hex): e -> 1
    ARRAY_SIZE(array): array[10] -> 10
     
    /****** MACRO ******/
    __LINE__: 50
    __FILE__: micro.c
    __DATE__: Dec 28 2010
    __TIME__: 19:25:10
    __func__: main
    hello __STDC__
     
    /****** sizeof() ******/
    sizeof(char): 1
    sizeof(signed char): 1
    sizeof(unsigned char): 1
    sizeof(short): 2
    sizeof(signed short): 2
    sizeof(unsigned short): 2
    sizeof(int): 4
    sizeof(signed int): 4
    sizeof(unsigned int): 4
    sizeof(long): 8
    sizeof(signed long): 8
    sizeof(unsigned long): 8
    sizeof(long long): 8
    sizeof(signed long long): 8
    sizeof(unsigned long long): 8
    sizeof(float): 4
    sizeof(double): 8 
    
    

    ==========================================

    C宏定义的简单总结

    1,防止一个头文件被重复包含 
    #ifndef BODYDEF_H 
    #define BODYDEF_H 
      //头文件内容 
    #endif 
    2,得到指定地址上的一个字节或字 
    #define  MEM_B( x )  ( *( (byte *) (x) ) ) 
    #define  MEM_W( x )  ( *( (word *) (x) ) ) 
    3,得到一个field在结构体(struct)中的偏移量 
    #define FPOS( type, field ) ( (dword) &(( type *) 0)-> field )
    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
    _STDC_
     
    宏中"#"和"##"的用法
    我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.
    #define STR(s)     #s 
    #define CONS(a,b)  int(a##e##b) 
    Printf(STR(vck));           // 输出字符串"vck" 
    printf("%d/n", CONS(2,3));  // 2e3 输出:2000
    当宏参数是另一个宏的时候 
    需要注意的是凡宏定义里有用"#"或"##"的地方宏参数是不会再展开. 
    #define A          (2) 
    #define STR(s)     #s 
    #define CONS(a,b)  int(a##e##b) 
    printf("%s/n", CONS(A, A));               // compile error  
    这一行则是: 
    printf("%s/n", int(AeA)); 
    INT_MAX和A都不会再被展开, 然而解决这个问题的方法很简单. 加多一层中间转换宏. 
    加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数
    #define STR(s)      _STR(s)          // 转换宏 
    #define CONS(a,b)   _CONS(a,b)       // 转换宏 
    printf("int max: %s/n", STR(INT_MAX));          // INT_MAX,int型的最大值,为一个变量 #include<climits> 
    输出为: 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__在第二层才能被解开;
    2、填充结构 
    #define  FILL(a)   {a, #a}
    enum IDD{OPEN, CLOSE}; 
    typedef struct MSG{ 
      IDD id; 
      const char * msg; 
    }MSG;
    MSG _msg[] = {FILL(OPEN), FILL(CLOSE)}; 
    相当于: 
    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、得到一个数值类型所对应的字符串缓冲大小 
    #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"]; 
    这里相当于: 
    char  buf[11]; 
     
    ==========================================
     
    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(xxx) ((byte) ((word)(xxx) & 255))
    #define WORD_HI(xxx) ((byte) ((word)(xxx) >> 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)))
     
    19,使用一些宏跟踪调试
    A N S I标准说明了五个预定义的宏名。它们是:
    _ L I N E _ (两个下划线),对应%d
    _ F I L E _    对应%s
    _ D A T E _   对应%s
    _ T I M E _   对应%s
    _ 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%s”,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
            
    解决方法: #difne DO(a,b) do{a+b;/
                       a++;}while(0)
     
    ==========================================
    
    宏中"#"和"##"的用法 
    一、一般用法 
    我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 
    用法: 
    #include<cstdio> 
    #include<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; 
    }
    二、当宏参数是另一个宏的时候 
    需要注意的是凡宏定义里有用''#''或''##''的地方宏参数是不会再展开.
    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 #include<climits> 
    这行会被展开为: 
    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型的最大值,为一个变量 #include<climits> 
    输出为: 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__在第二层才能被解开;
    2、填充结构 
    #define FILL(a)   {a, #a}
    enum IDD{OPEN, CLOSE}; 
    typedef struct MSG{ 
    IDD id; 
    const char * msg; 
    }MSG;
    MSG _msg[] = {FILL(OPEN), FILL(CLOSE)}; 
    相当于: 
    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、得到一个数值类型所对应的字符串缓冲大小 
    #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"]; 
    这里相当于: 
    char buf[11];
    

    ==========================================

    参考:
    C宏定义的简单总结
    http://www.cppblog.com/BlueSky/archive/2007/11/20/37000.html

    宏中"#"和"##"的用法
    http://blog.csdn.net/Sunboy_2050/archive/2010/11/12/6004159.aspx

  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/muahao/p/6053979.html
Copyright © 2011-2022 走看看