15个预处理命令和23个软件中常用的宏定义整理

目录

1.C语言常用的预处理命令

2.C语言常用宏

1.__FILE__ 

2.__LINE__

3.__FUNCTION__

4. 防止一个头文件被重复包含

5. 重新定义一些类型

6. 得到指定地址上的一个字节或字

7. 求最大值和最小值

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

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

10. 按照LSB格式把两个字节转化为一个Word

11. 按照LSB格式把一个Word转化为两个字节

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

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

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

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

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

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

18. 防止溢出的一个方法

19. 返回数组元素的个数

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

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

22. 使用一些宏跟踪调试

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


1.C语言常用的预处理命令

C语言中,预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换,预处理过程还会删除程序中的注释和多余的空白符号。预处理指令是以#开头的代码行,#必须是该行除了空白字符外的第一个字符。#后是指令关键字,在#和指令关键字之间允许存在若干空白字符。

#define定义一个预处理宏
#undef 取消宏的定义
#include 包含文件命令
#include_next 与#include相似, 但它有着特殊的用途
#if 编译预处理中的条件命令, 相当于C语法中的if语句
#ifdef判断某个宏是否被定义, 若已定义, 执行随后的语句
#ifndef 与#ifdef相反, 判断某个宏是否未被定义
#elif与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else
#endif#if, #ifdef, #ifndef这些条件命令的结束标志.
#defined 与#if, #elif配合使用, 判断某个宏是否被定义
#line 标志该语句所在的行号
#将宏参数替代为以参数值为内容的字符窜常量
## 将两个相邻的标记(token)连接为一个单独的标记
#pragma说明编译器信息#warning,显示编译警告信息
#error 显示编译错误信息

2.C语言常用宏

想提高效率,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。下面列举一些成熟软件中常用的宏定义。

1.__FILE__ 

宏在预编译时会替换成当前的源文件名。

2.__LINE__

宏在预编译时会替换成当前的行号。

3.__FUNCTION__

宏在预编译时会替换成当前的函数名称。

4. 防止一个头文件被重复包含

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

5. 重新定义一些类型

防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。

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

6. 得到指定地址上的一个字节或字

#define MEM_B( x ) ( *( (byte *) (x) ) )
#define MEM_W( x ) ( *( (word *) (x) ) )

7. 求最大值和最小值

#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

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

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

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

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

10. 按照LSB格式把两个字节转化为一个Word

#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )

11. 按照LSB格式把一个Word转化为两个字节

#define FLOPW( ray, val ) \
(ray)[0] = ((val) / 256); \
(ray)[1] = ((val) & 0xFF)


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

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

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

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

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

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

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

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

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

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

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

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

18. 防止溢出的一个方法

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

19. 返回数组元素的个数

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

20. 返回一个无符号数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) )

21. 对于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)))

22. 使用一些宏跟踪调试

A N S I标准说明了五个预定义的宏名。它们是:

_ D A T E _
_ T I M E _
_ S T D C _

如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。

_ D AT E _宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。

源代码翻译到目标代码的时间作为串包含在_ T I M E _中。串形式为时:分:秒。

如果实现是标准的,则宏_ S T D C _含有十进制常量1。如果它含有任何其它数,则实现是非标准的。

可以定义宏,例如: 当定义了_DEBUG,输出数据信息和所在文件所在行

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

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

//例如:

#define ADD(a,b) (a+b)

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

//例如:
#difne DO(a,b) a+b;\
a++;

//应用时:

if(….)
DO(a,b); //产生错误
else

//解决方法:

#difne DO(a,b) do{a+b;\
a++;}while(0)

1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除。

2.未经原作者允许不得转载本文内容,否则将视为侵权;

3.转载或者引用本文内容请注明来源及原作者;

4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

下面是我的个人微信公众号,关注【一个早起的程序员】精彩系列文章每天不断。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个早起的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值