出处: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\n",STR(ABC));
printf("%d\n",CONS(,));
return ;
}
/*
root@oucaijun:/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 ;
}
/*
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\n", \
__FILE__, __LINE__, __FUNCTION__,"hello", ctime(&t)); return ;
}
/*
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\n",msg, __FILE__, __LINE__, date);\
}while() #else
#define DEBUGMSG(msg,date)
#endif int main()
{ time_t now;
time(&now); DEBUGMSG("hello",ctime(&now)); return ;
}
/*
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)

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

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

    1.  头文件定义例如以下: /* declears in "funcs.h" */ FUNC_1(ID_FUN1_001) FUNC_1(ID_FUN1_002) FUNC_2( ...

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

    将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 ...

  3. C 语言宏定义

    C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; ...

  4. C语言 宏定义之可变参数

    可变参数宏定义 C99编译器标准允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏.可变参数宏就像下面这个样子: #define dbgprint(. ...

  5. C语言宏定义使用技巧

    写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义...... 1.防止一个头文件被重复包含 #ifndef COMDEF_ ...

  6. 【转】C语言宏定义的几个坑和特殊用法

    总结一下C语言中宏的一些特殊用法和几个容易踩的坑.由于本文主要参考GCC文档,某些细节(如宏参数中的空格是否处理之类)在别的编译器可能有细微差别,请参考相应文档. 宏基础 宏仅仅是在C预处理阶段的一种 ...

  7. C 语言宏定义函数编写时 do-while 的妙用和一些注意事项

    在 C 语言中,我们都知道可以用宏定义来编写函数,一般称为宏函数.如果一个宏函数比较复杂,那么在编写这样的宏函数是有一定技巧和注意事项的.文章给出一些我认为值得关注的地方,以及一些注意事项(个人建议) ...

  8. C语言宏定义时#(井号)和##(双井号)的用法1

    #在英语里面叫做 pound 在C语言的宏定义中,一个#表示字符串化:两个#代表concatenate 举例如下: #include <iostream> void quit_comman ...

  9. C语言宏定义时#(井号)和##(双井号)的用法

    C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...

随机推荐

  1. python字符串操作总结

    python中有各种字符串操作,一开始python有个专门的string模块,要使用需先import string.后来从python2.0开始,string方法改用str.method()形式调用, ...

  2. Android JNI入门第一篇——HelloJni

    android支持使用NDK开发C程序,关于配置NDK环境问题应该不用再赘述了,这个网上有很多,这里通过一篇实例来讲述简单的JNI开发,大家可以参考这篇文章(Get Your Eclipse-Inte ...

  3. Android的电源管理框架

    Android的电源管理框架 Android通过锁和定时器来切换系统的状态,使系统的功耗降至最低,整个系统的电源管理框架分成五个部分:应用层,framework层,JNI层,HAL层和内核层.电源管理 ...

  4. 记载abp中Dbcontext的疑问

    q:abp中httpcontext如何在一次请求中保证获取的是相同的实例. 大牛的原话: LifestylePerWebRequest does not works good with async. ...

  5. React Native-目前最火的前端技术?

    做为一名产品经理,你是否遇到过这样的窘境,“帮我把字体调成 16号呗,颜色变成 #FFFF00FF,老大说这里最好改一下”,作为一名 app 的开发只能无奈但心里窃喜的告诉你,“只能等下个版本了,必须 ...

  6. 关于MooTools你应该熟知的6个基本知识

    MooTools是一个精简.模组化同时也面向对象的JavaScript框架,它设计给中等和进阶的JavaScript开发人员使用.使用 MooTools优美.详细而条理分明的API,可让你写出强大.富 ...

  7. Nginx+uwsgi+supervisor+Ubuntu+flask

    Nginx+uwsgi+supervisor+Ubuntu+flask Nginx+uwsgi+supervisor在Ubuntu上部署flask应用 网上找了许多讲关于Flask应用部署的文章几乎都 ...

  8. Python: 在Unicode和普通字符串之间转换

    Unicode字符串可以用多种方式编码为普通字符串, 依照你所选择的编码(encoding): <!-- Inject Script Filtered --> Toggle line nu ...

  9. Objective-C 类,实例成员,静态变量,对象方法,类方法(静态方法),对象,

    Objective-C 类,实例成员,静态变量,对象方法,类方法(静态方法),对象, 一.类 在ios中,类的声明和实现时分离的,也就是说不能写在同一个文件中,声明放在 .h文件中,实现放在 .m 文 ...

  10. [置顶] mybatis批量新增系列之有主键的表的批量新增

    前面介绍了无主键的表的批量插入,文章地址:http://blog.csdn.net/zhouxiaoyun0228/article/details/9980181 但是在开发中往往许多的表是需要主键的 ...