博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言宏定义技巧
阅读量:7176 次
发布时间:2019-06-29

本文共 3502 字,大约阅读时间需要 11 分钟。

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

 

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

 

一、一般用法

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

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

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

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 
#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;} /*root@oucaijun:/work/dcc# gcc *.c; ./a.out "test.c"__FILE__*/

 2.宏跟踪调试

#include 
#include
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 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 
#include
#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)#endifint 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) 

 

转载地址:http://kkbzm.baihongyu.com/

你可能感兴趣的文章
(转载)Http 请求处理流程
查看>>
GetVersion和GetVersionEx
查看>>
php采集利器snoopy应用技巧
查看>>
我的友情链接
查看>>
安装虚拟机shell脚本
查看>>
[Python]第一个爬虫练习
查看>>
rpm,yum,权限
查看>>
tomcat应用转到weblogic上时的问题
查看>>
vSphere 5.5 vCenter迁移至分布式交换机
查看>>
第二次作业
查看>>
viewport ——视区概念
查看>>
拓扑规则翻译函数(转)
查看>>
数据结构--图的定义和存储结构
查看>>
linux常用命令
查看>>
Appium自动化测试1 - 安装部署
查看>>
Bzoj 1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐 深搜,bitset
查看>>
UVa294 Divisors
查看>>
洛谷P3406 海底高铁
查看>>
1、JUC--volatile 关键字-内存可见性
查看>>
uboot arp地址解析
查看>>