C语言_01_宏定义使用技巧
2017-12-08 08:35
369 查看
对于底层软件开发的工程师, 对宏定义肯定不陌生吧, 我在写代码的时候就习惯使用宏定义, 代码结构清晰, 修改也及其便捷, 在以下场景时使用宏定义的优势.
1. 防止头文件被重复包含
#ifndef MAIN_H #define MAIN_H ..... //代码部分, 一般为全局变量, 函数声明 #endif
2. 简单函数实现
#define ABS(x) ((x)>=0 ? (x):(-x);) //取绝对值 #define ADD(x,y) ((x)+(y)) //加法 #define MAX(x,y) ((x)>(y) ? (x):(y)) //最大值
3. 获取变量地址
#define PTR(var) ((UINT32*)(void*)&(var))
4. 字节拼字/字拆字节
#define BYTE_TO_WORD(ray) ((word)((ray)[0]*256)+(ray)[1]) //字节拼字 LSB方式 #define WORD_TO_BYTE(ray,val) \ (ray)[0] = ((val)/256); \ (ray)[1] = ((val) & 0xFF) //字拆字节
5. 类型重定义, 使代码跨平台和编译器
typedef unsigned char UINT8; typedef signed char INT8; typedef unsigned short UINT16; typedef signed short INT16; typedef unsigned long int UINT32; typedef signed long int INT32; typedef UINT8 BOOL;
6. 获取成员在结构体中的偏移/所占字节数
#define MEM_OFF(type, field) (((UINT32)&(type *)0)->field) //偏移 #define MEM_SIZE(type, field) (sizeof(type *)0)->field) //所占字节数
7. 获取指定地址上的字节/半字/字
#define ADDR_BYTE(x) (*(UNIT8*)(x)) //字节 #define ADDR_BYTE(x) (*(UNIT16*)(x)) //半字 #define ADDR_WORD(x) (*(UINT32*)(x)) //字
8. 大小写转换
#define WORD_LOW(c) ((c)>='A' && (c)<='Z') ? ((c)+0x20) : (c)) #define WORD_UP(c) ((c)>='a' && (c)<='z') ? ((c)-0x20) : (c))
9. 检查是否是十进制/十六进制
#define DEC_CHK(c) ((c)>='0' && (c)<='9') //十进制 #define HEX_CHK(c) ((c)>='0' && (c)<='9') || \ ((c)>='A' && (c)<='F') || \ ((c)>='a' && (c)<='f') //十六进制
10. 获取半字的高低位
#define WORD_LO(c) (UINT8) ((UINT16)(c) & 0xFF)) //低8位 #define WORD_HI(c) (UINT8) ((UINT16)((c)>>8) & 0xFF)) //高8位
11. 结构体初始化
typedef struct //结构体定义 { uint16_t prescaler; /**< Prescaler. */ uint8_t interrupt_priority; /**< Interrupt priority. */ uint8_t tick_latency; /**< Maximum length of interrupt handler in ticks (max 7.7 ms). */ bool reliable; /**< Reliable mode flag. */ } nrf_drv_rtc_config_t; #define NRF_DRV_RTC_DEFAULT_CONFIG \ //使用宏初始化结构体成员变量 { \ .prescaler = RTC_FREQ_TO_PRESCALER(RTC_DEFAULT_CONFIG_FREQUENCY), \ .interrupt_priority = RTC_DEFAULT_CONFIG_IRQ_PRIORITY, \ .reliable = RTC_DEFAULT_CONFIG_RELIABLE, \ .tick_latency = RTC_US_TO_TICKS(NRF_MAXIMUM_LATENCY_US, RTC_DEFAULT_CONFIG_FREQUENCY), \ } static nrf_drv_rtc_config_t const m_rtc_config = NRF_DRV_RTC_DEFAULT_CONFIG;
12. 防止溢出
#define OVERFLOW(val) (val = ((val)+1 > (val)) ? (val)+1 : (val))
13. 求数组元素个数
#define ARR_NUM(a) ((sizeof(a)/sizeof(a[0]))
14. 求最接近的倍数值 //常用于内存分配
#define POWER8(x) ((((x)+7)/8)*8)
15. 用于跟踪调试 //ANSI标准(仅限于标准编译器, 非标准编译器可能支持不全或不支持)
__LINE__ //对应 %d 表示当前指令所在行, 是个整型数 __FILE__ //对应 %s 表示当前指令所在文件, 包含完整路径 __DATE__ //对应 %s 包含形式为月/日/年的字符串, 表示源文件被翻译到代码时的日期 __TIME__ //对应 %s 包含源代码翻译到目标代码的时间, 字符串形式为 时:分:秒 __STDC__ //含有十进制常量1, 如果它含有任何其它数,则实现是非标准的
16. 调试使用
#ifdef __DEBUG #define DEBUG_MSG(msg, date) printf(msg); printf("%d%d%d", date, __LINE__, __FILE__) #else #define DEBUG_MSG(msg, date)
17. 防止多次初始化(只能进行一次)
#define NRF_LOG_INTERNAL_FLUSH() \ do { \ while (NRF_LOG_INTERNAL_PROCESS()); \ } while (0)