您的位置:首页 > 编程语言 > C语言/C++

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息