C语言宏定义的20种用法-网站语言交流社区-弘客联盟新手区-弘客联盟

C语言宏定义的20种用法

用好C语言的宏定义可以让代码更加简洁漂亮。宏定义有更好的可读性、增加可移植性、方便编写代码等优点。接下来向大家介绍常用宏定义的几种用法。

1. 防止头文件重复包含

#ifndef COMDEF_H
#define COMDEF_H
//头文件内容
#endif

2. 重新定义类型

重新定义类型,避免在不同平台和编译器上,类型的字节不同,因而出bug,方便代码的移植。

typedef unsigned char boolean; /* 布尔类型 */
typedef unsigned long int uint64; /* 无符号64位类型 */
typedef unsigned int uint32; /* 无符号32位类型 */
typedef unsigned short uint16; /* 无符号16位类型 */
typedef unsigned char uint8; /* 无符号8位类型 */
typedef signed long int uint64; /* 64位类型 */
typedef signed int int32; /* 32位类型 */
typedef signed short int16; /* 16位类型 */
typedef signed char int8; /* 8位类型 */

或者是下面这样:

typedef unsigned char byte; /* 无符号8位类型 */
typedef unsigned short word; /* 无符号16位类型 */
typedef unsigned int dword; /* 无符号32位类型 */
typedef unsigned char uint1; /* 无符号8位类型 */
typedef unsigned short uint2; /* 无符号16位类型 */
typedef unsigned int uint4; /* 无符号32位类型 */
typedef unsigned long uint8; /* 无符号64位类型 */
typedef signed char int1; /* 8位类型 */
typedef signed short int2; /* 16位类型 */
typedef signed int int4; /* 32位类型 */
typedef signed int int8; /* 64位类型 */
typedef signed int sint63; /* 64位类型 */
typedef signed int sint31; /* 32位类型 */
typedef signed short sint15; /* 16位类型 */
typedef signed char sint7; /* 8位类型 */

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

5. 得到一个field在结构体(struct)中的偏移量

#define FPOS(type, field) \
/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */

6. 得到一个结构体中field所占用的字节数

#define FSIZ(type, field) (sizeof(((type*) 0) -> field))

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)

9. 得到一个变量的地址(word宽度)

#define B_PTR(var) ((byte*)(void*) & (var))
#define W_PTR(var) ((word*)(void*) & (var))

10. 得到一个字的高位和低位字节

#define WORD_LO(xxx) ((byte)((word)xxx) & 255)
#define WORD_HI(xxx) ((byte)((word)xxx) >> 8)

11. 返回一个比X大的最接近的8的倍数

#define RND8(x) ((((x) + 7) / 8) * 8)

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

#define UPCASE(c) (((c) >= 'a' && (c) <= 'z')? ((c) - 0x20): (c))

13. 判断字符是不是10进制的数字

#define DECCHK(c) ((c) >= '0' && (c) <= '9')

14. 判断字符是不是16进制的数字

#define HEXCHK(c) (((c) >= '0' && (c) <= '9') ||\
((c) >= 'A' && (c) <= 'F') ||\
((c) >= 'a' && (c) <= 'f'))

15. 防止溢出的一个方法

#define INC_SAT(val) (val = ((val)+1 > (val))? (val)+1: (val))

16. 返回数组元素的个数

#define ARR_SIZE(a) ( sizeof((a)) / sizeof((a[0]))

17. 返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)

#define MOD_BY_POWER_OF_TWO(val, mod_by) \
((dword)(val) & (dword)((mod_by)-1))

18. 对于IO空间映射在存储空间的结构,输入输出处理

#define inp(port) (*((volatile byte*) (port)))
#define inpw(port) (*((volatile word*) (port)))
#define inpdw(port) (*((volatile dword*)(port)))
#define outp(port, val) (*((volatile byte*) (port)) = ((byte) (val)))
#define outpw(port, val) (*((volatile word*) (port)) = ((word) (val)))
#define outpdw(port, val) (*((volatile dword*) (port)) = ((dword) (val)))

19. 使用一些宏跟踪调试

A N S I标准定义了5个预定义宏:

__LINE__
__FILE__
__DATE__
__TIME__
__STDC__

如果编译器不是标准的,可能只支持上面几个宏或根本不支持。另外,编译器或许支持其他的预定义宏。

__DATE__:它文本替换为“Mmm dd yyy”格式的日期,表示代码预处理时的日期。

__LINE__:当前源代码的行号,它可以随着#line指令而改变。

__FILE__:当前源文件的名称。

__TIME__: 源代码编译的时间。

__STDC__:如果当前编译器是标准的,它的值为1,否则是未定义。

可以定义宏,比如定义_DEBUG_宏输出数据信息和代码所在文件所在行。

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

20. 宏定义防止使用时错误用小括号包含。

譬如:

#define ADD(x, y) (x + y)

可以使用 do{}while(0) 包含多条语句防止出错,譬如:

#define DO(x, y) (x + y); \
x++;

再者:

if(a > b)
    DO(a, b);//出现错误
else
    ...

这并不符合if语句的用法,因修改为:

#define DO(x, y) do{ \
x + y; \
x++; \
}while(0)

-END-

请登录后发表评论

    没有回复内容

随便看看