几种典型宏程序的编写方法
宏是程序设计语言一个重要的内容,对于一些步骤少却又使用频繁的操作,考虑到程序容量和执行效率的问题我们一般不将其封装为函数而是以宏的形式出现。对于单片机程序这一点尤为突出。宏语言分类非常广泛,这里介绍C语言常用的一些宏的编写方法。
二进制数宏
- 01
利用二进制宏可以解决C语言不能直接使用二进制量的问题,宏核心代码如下: #define LONG_TO_BIN(n) \ ( \ ((n >> 21) & 0x80) | \ ((n >> 18) & 0x40) | \ ((n >> 15) & 0x20) | \ ((n >> 12) & 0x10) | \ ((n >> 9) & 0x08) | \ ((n >> 6) & 0x04) | \ ((n >> 3) & 0x02) | \ ((n ) & 0x01) \ ) #define BIN(n) LONG_TO_BIN(0x##n##L) 我们可以直接使用BIN(11100111)这种形式来使用常量,这就是最直观的二进制形式,非常方便,下载我们新建工程,测试代码如图:
- 02
由数制转换基本知识可知 二进制11000111对应十进制的199,我们使用BIN(11000111)与使用199具有同样的效果,程序运行结果验证了这一点。
位清除和设置宏
- 01
对于位操作,C语言提供了位域,但是位域要结合结构体使用,而由于C语言对字节对齐的方式未给出严格定义,不同编译器对于结构体的内存布局会有不同的实现方式,这就导致位域存在兼容性问题。我们可以使用位清除和未设置宏来解决这一问题: #define SET_BIT(var,BIT_POS) {var |= (0x01 << ((BIT_POS) % 8));} #define CLR_BIT(var,BIT_POS) {var &= (~(0x01 << ((BIT_POS) % 8)));} 其中SET_BIT(var, BIT_POS)为位设置宏,即设置变量var的第BIT_POS位为1,其中BIT_POS由0到该变量的最长长度 - 1,比如对于8位变量它的取值就是0~7。CLR_BIT(var, BIT_POS)与之类似,只不过CLR_BIT是将对应的位清零。 通过测试可以更好地理解,图为测试代码具体实现:
- 02
图为程序的运行结果,a最开始是0,而运行SET_BIT(a, 0)后变成了1,也就是a的最低位被SET_BIT置位了,而接着运行CLR_BIT(a, 0)后,a又变成0了,这也就是a的最低位被CLR_BIT清零了。
避免容量浪费的位编辑宏
- 01
前面介绍的位设置和位清除宏,可以实现变量的位操作,但是对于SET_BIT(var, BIT_POS)如果将BIT_POS传入变量,那么编译器会产生多余的代码造成空间浪费,这里再介绍一种避免这种问题的位编辑宏,分别为SET_BITn()和CLR_BITn(),分别对给定的变量的指定位置位和清零。具体实现如下: #define BIT0_SEL 0x01 #define BIT1_SEL 0x02 #define BIT2_SEL 0x04 #define BIT3_SEL 0x08 #define BIT4_SEL 0x10 #define BIT5_SEL 0x20 #define BIT6_SEL 0x40 #define BIT7_SEL 0x80 #define SET_BITn(var,BITn_SEL) {var |= (BITn_SEL);} #define CLR_BITn(var,BITn_SEL) {var &= (~(BITn_SEL));} 图中位该宏的测试代码:
- 02
图为程序的运行结果,初始状态a为0, 当我们执行SET_BITn(a, BIT0_SEL);后a的值变成了1,即a的最低位被SET_BITn置位了,接下来我们执行CLR_BITn(a, BIT0_SEL),这是a的值变成0了,这是说a的最低位被CLR_BITn清零了。这验证了我们宏程序的准确性。
计算两个数字差的绝对值
- 01
有时候我们需要获得两个量的差距,这个其实可以通过判断语句来实现,不过这样看起来显的代码有点臃肿了,比如,将变量a和b差的绝对值赋值给c我们可以这样做: if(a > b) { c = a - b; } else { c = b - a; } 很简单的一个功能,但却占用了8行,感觉有点多了,不如试试下面的宏程序: #define ABS(NUM1,NUM2) ((NUM1) > (NUM2) ? (NUM1 - NUM2):(NUM2 - NUM1)) 这样便可以写作: c = ABS(a, b); 而且你还可以倒过来这样写: c = ABS(b, a); 仅仅才一行,程序看起来是不是感觉清爽多了? 图中给出一个测试代码,帮助进一步理解这个宏程序:
- 02
图中为ABS测试程序的运行结果,可以看出当a = 0, b = 10时a和b之间差10各数,与程序运行结果一致。而当a = 10, b = 10时,它们之间差0各数,程序执行ABS(a,b)后结果为0,也是一致的。最后当a = 11, b = 10,即a和b之间差1个数,程序执行ABS(a, b)后结果也是1.