C语言宏定义技巧

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

  • 宏中"#"和"##"的用法

一、一般用法

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

#include <stdio.h>

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

int main()
{
    printf("%s\n",STR(ABC));
    printf("%d\n",CONS(2,3));
    return 0;
}
/*
[email protected]:/work/dcc# gcc *.c; ./a.out
ABC
2000
*/

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

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 CONS(a,b)  ((int)(a##e##b) )

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

这一行则是:

printf("%s\n", 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\n", FILENAME);

    // _GET_FILE_NAME(f)在展开的时候,引用了宏 __FILE__
    // 根据_GET_FILE_NAME的定义,它的内部遇到宏并不会展开,而只是把其当作字符串而已,得不到正确的结果
    static char FILENAME2[] = _GET_FILE_NAME(__FILE__);//__FILE__
    printf("%s\n", FILENAME2);

    return 0;
}
/*
[email protected]:/work/dcc# gcc *.c; ./a.out
"test.c"
__FILE__
*/
  • 下面列举软件中常用得一些宏定义:

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

19,使用一些宏跟踪调试

当定义了_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\n",msg, __FILE__, __LINE__, date);    }while(0)

#else
    #define DEBUGMSG(msg,date)
#endif

#if 1

int main()
{

    time_t now;
    time(&now);

    DEBUGMSG("hello",ctime(&now));

    return 0;
}

#endif

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

用小括号包含.

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

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

a++;}while(0)

时间: 2024-10-07 22:26:24

C语言宏定义技巧的相关文章

C语言宏定义技巧——多次包含头文件内容不同

1.  头文件定义如下: /* declears in "funcs.h" */ FUNC_1(ID_FUN1_001) FUNC_1(ID_FUN1_002) FUNC_2(ID_FUN2_001) FUNC_2(ID_FUN2_002) 2.  多次包含头文件 #define FUNC_1(opt) opt, #define FUNC_2(opt) enum aaa { #include "funcs.h" ID_FUN1_END }; #undef FUNC_

C语言宏定义技巧——多次包括头文件内容不同

1.  头文件定义例如以下: /* declears in "funcs.h" */ FUNC_1(ID_FUN1_001) FUNC_1(ID_FUN1_002) FUNC_2(ID_FUN2_001) FUNC_2(ID_FUN2_002) 2.  多次包括头文件 #define FUNC_1(opt) opt, #define FUNC_2(opt) enum aaa { #include "funcs.h" ID_FUN1_END }; #undef FUN

将C语言宏定义数值转换成字符串!

将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 阅读数:10185 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/happen23/article/details/50602667 适用场景举例 流媒体处理系统中,采样率是个很重要的参数,很多地方都要用,如果用来分配内存,则 #define S

常用的C语言宏定义

常用的C语言宏定义 1,防止一个头文件被重复包含      #ifndef COMDEF_H      #define COMDEF_H          //头文件内容      #endif       2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植.       typedef   unsigned char       boolean;      /* Boolean value type. */             typedef   uns

转载--c语言宏定义(1)

作者:独舞风 链接:c语言宏定义(1) 1.为什么要有宏定义? 代码中某个特定数值需要参与运算,而且该数值作用于多个地方,当需要对该数值进行修改时,希望只改动一个地方就能实现该数值的全部更新:即便某个数值只用到一次,当修改时也会面临搜索阅读大量代码.数值含义不明晰的问题:某些“操作块”封装成函数时,调用函数开销(保存上下文环境.参数调用.堆栈分配等)太大影响效率,不封装则需要多次输入相同的“操作块”内容,并且修改麻烦容易出现不一致的问题,这时就需要把“操作块”定义成宏,该方案本质是“空间换时间”

转载--c语言宏定义(2)

作者:独舞风 链接:c语言宏定义(2) 1.如何区分宏定义中的“宏名称”和“宏字符串”?对于带参数的宏又该注意什么? 在宏定义中,“宏名称”和“宏字符串”是通过“空格”来区分的,在宏的扩展中,空格会对扩展的结果造成很大的影响.编译器在处理时宏定义时,首先从“#define”后第一个空格开始读取字符串,直到遇见下一个空格为止,两个空格之间的字符串为“宏名称”,确定好“宏名称”之后,本行的所有其他字符串都为“宏字符串”.图示:#define + N个空格(1 < N) + 宏名称(中间没有空格) +

C 语言宏定义

C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; PRINT_STR(str); 结果如下:abcd2.现在我期望打印出,str=abcd, 容易想到的解决办法是: #define PRINT_STR(s) printf("s" "=" "%s",s.c_str()) 打印出来的结果是 s=abcd

C语言宏定义使用技巧

写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植. typedef  unsigned char      boolean;     /* Boolean value type. */ type

iOS开发分分钟搞定C语言 —— 宏定义和关键字

一.宏定义 概念:宏定义实质是一个预编译指令,在程序未运行之前将某些指令付给相应的变量.一般情况预处理指令都是以#号开头的,所以宏定义也是以#开发,关键字为#define(定义宏定义),#undef(结束宏定义). 定义格式及作用域 一般宏定义都定义在程序的首段: #define 宏名 值. 宏定义的作用域:从开始定义的那行起,一直到文件末尾,虽然默认情况下宏定义的作用域是从定义的那一行开始, 一直到文件末尾.但是我们也可以通过对应的关键字#under提前结束宏定义的作用域. 宏定义规范 一般情