Chinaunix首页 | 论坛 | 博客
  • 博客访问: 46602
  • 博文数量: 17
  • 博客积分: 455
  • 博客等级: 下士
  • 技术积分: 171
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-07 21:27
文章分类

全部博文(17)

文章存档

2013年(8)

2012年(9)

我的朋友

分类: LINUX

2013-05-03 16:28:00

写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等,参考一些网上的文章和自己的一下总结。

1、防止头文件的重复包含,示例如下:
#ifndef __LIST_H__
#define __LIST_H__

//code.....

#endif 


2、重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。

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

3、使用一些宏用于跟踪调试

 __FILE__;  文件名
__LINE__;  行号
__FUNCTION__; 函数名
__DATE__;        表示编译时刻的日期字符串
__TIME__ ;      表示编译时刻的时间字符串   
GCC都支持以上的这几个宏。
 

当定义了_DEBUG,输出数据信息和所在文件所在行

#ifdef _DEBUG

#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)

#else

#define DEBUGMSG(msg,date)

#endif


4、在宏定义中使用do { xxx } while(0) 防止宏中多语句的问题
#define DO(a, b) (a) + (b); \
(a)++;
如果在if语句下面,
if (xxx)
    DO(2, 3)
//展开后
if (xxx)
    2 + 3;
    2++;   //会将这条语句漏掉
解决的办法是在宏定义中加入do{ } while(0)
#define DO(a, b) do {\
    (a) + (b);
    (a)++;
} while (0)

5、宏定义中"#"和"##"的用法
a:一般用法
    "#"将宏参数变为一个字符串; "##"将两个宏参数连接在一起。

点击(此处)折叠或打开

  1. #include <stdio.h>

  2. #define _STR(x) #x
  3. #define _CONS(a,b) (int)(a##2##b)

  4. int main()
  5. {
  6.     printf("_STR(X) = %s\n", _STR(afdsf));
  7.     printf("_CONS(a,b) = %d\n", _CONS(1,3));

  8.     return 0;
  9. }
b:当宏参数是另外一个宏的时候
注意:当宏定义里面有"#"和"##"的地方,宏参数不会展开。


点击(此处)折叠或打开

  1. #include <stdio.h>

  2. #define XXX adfasffd
  3. #define _STR(x) #x
  4. #define STR(x) _STR(x)

  5. int main()
  6. {
  7.     printf("_STR(X) = %s\n", _STR(afdsf));
  8.     printf("STR(X) = %s\n", STR(XXX));  // 加多一层中间转换宏,在这层宏中将参数先替换,再在_STR宏中转换为字符串

  9.     return 0;
  10. }


'#''##'的一些应用特例
 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];

阅读(931) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~