• C语言宏定义技巧


    出处:http://blog.chinaunix.net/uid-14022540-id-2849095.html

    1.宏中"#""##"的用法

    一、一般用法

    我们使用#把宏参数变为一个字符串,##把两个宏参数贴合在一起

    #include <stdio.h>
    
    #define CONS(a,b) ((int)(a##e##b))
    #define STR(s) #s
    
    int main()
    {
        printf("%s
    ",STR(ABC));
        printf("%d
    ",CONS(2,3));
        return 0;
    } 
    /*
    root@oucaijun:/work/dcc# gcc *.c; ./a.out 
    ABC
    2000
    */

    二、当宏参数是另一个宏时: 需要注意的是凡宏定义里有用'#''##'的地方宏参数是不会再展开.

    1, '#''##'的情况,自然展开:

    #define TOW      (2)

    #define MUL(a,b) (a*b)

     printf("%d*%d=%d ", TOW, TOW, MUL(TOW,TOW));

    这行的宏会被展开为:

    printf("%d*%d=%d ", (2), (2), ((2)*(2)));

    MUL里的参数TOW会被展开为(2). 

    2, 当有'#''##'的时候,'#''##'的地方宏参数不会再展开

    #define A          (2)

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

    printf("%s ", CONS(A, A));               // compile error  

    这一行则是:

    printf("%s ", int(AeA)); 

    然而解决这个问题的方法很简单. 加多一层中间转换宏: 凡是涉及到#, ## 的宏,使用另一个宏来包装它。

    #include <stdio.h>
    
    #define _GET_FILE_NAME(f) (#f)
    #define GET_FILE_NAME(f) _GET_FILE_NAME(f)
    
    int main()
    {
        // 根据GET_FILE_NAME(f)的定义,它并没有直接使用#,因此内部宏得以完整地展开,得到正确结果
        static char FILENAME[] = GET_FILE_NAME(__FILE__);//"test.c"
        printf("%s
    ", FILENAME);
    
        // _GET_FILE_NAME(f)在展开的时候,引用了宏 __FILE__ 
        // 根据_GET_FILE_NAME的定义,它的内部遇到宏并不会展开,而只是把其当作字符串而已,得不到正确的结果
        static char FILENAME2[] = _GET_FILE_NAME(__FILE__);//__FILE__
        printf("%s
    ", FILENAME2);
    
        return 0;
    } 
    /*
    root@oucaijun:/work/dcc# gcc *.c; ./a.out 
    "test.c"
    __FILE__
    */

     2.宏跟踪调试

    #include <stdio.h>
    #include <time.h>
    
    int main()
    {
        time_t t;
        time(&t);
        
        printf("file:%s, line:%d, function:%s, msg:%s, date:%s
    ", 
            __FILE__, __LINE__, __FUNCTION__,"hello", ctime(&t));
        
        return 0;
    }
    /*
    root@oucaijun:/work/dcc# gcc *.c; ./a.out 
    file:1.c, line:11, function:main, msg:hello, date:Tue Jul 21 17:03:01 2015
    */
    当定义了_DEBUG,输出数据信息和所在文件所在行

    #include <stdio.h> #include <time.h> #define _DEBUG #ifdef _DEBUG #define DEBUGMSG(msg, date) do{ printf("msg: %s; file:%s, line:%d, date:%s ",msg, __FILE__, __LINE__, date); }while(0) #else #define DEBUGMSG(msg,date) #endif int main() { time_t now; time(&now); DEBUGMSG("hello",ctime(&now)); return 0; } /* root@oucaijun:/work/dcc# gcc *.c; ./a.out msg: hello; file:1.c, line:22, date:Tue Jul 21 17:05:44 2015 */

     3.下面列举软件中常用得一些宏定义:

    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. */

     

    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) ) 

     

    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) 

     

    12,将一个字母转换为大写

     #define  UPCASE( c ) ( ((c) >= 'a' && (c) = '0' && (c) = '0' && (c) = 'A' && (c) = 'a' && (c)  (val)) ? (val)+1 : (val)) 

    20,宏定义防止使用是错误

    用小括号包含.

    do{}while(0)语句包含多语句防止错误

    eg: #define ADD(a,b) do{a+b;

                        a++;}while(0) 

  • 相关阅读:
    设计模式
    idea多个项目
    多个tomcat配置
    mysql数据库默认时间字段格式
    读取文件
    上传图片
    数据库创建用户授权
    统计12个月份的数据
    行列转换
    分页
  • 原文地址:https://www.cnblogs.com/mylinux/p/4664832.html
Copyright © 2020-2023  润新知