#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK
(MCDR2_ADDRESS)
#define BIT_MASK(_bf)(((1U<<(bw##_bf))-1)<<
(bs##_bf)
#define SET_BITS(_dst,_bf,_val)\
((_dst)=((_dst)&~(BIT_MASK(_bf)))I
(((_val)<<(bs##_bf))&(BIT_MASK(_bf))))
SET_BITS(MCDR2,MCDR2_ADDRESS,RegisterNumb
er);
解释1:
在#define中,标准只定义了#和##两种操作。#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串。
这主要是宏定义的问题,宏定义其实就是从最后一个一个替换到所有的define都替换完了。可以理解为重命名。
1.
SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);
MCDR2替换__dst
MCDR2_ADDRESS替换__bf
RegisterNumber替换__val,
SET_BITS(__dst, __bf, __val) 就变成
((MCDR2) = ((MCDR2) & ~(BIT_MASK(MCDR2_ADDRESS))) |(((RegisterNumber) << (bsMCDR2_ADDRESS)) & (BIT_MASK(MCDR2_ADDRESS))))
2.
#define BIT_MASK(__bf) (((1U << (bw ## __bf)) - 1) << (bs ## __bf))
即用(((1U << (bw ## __bf)) - 1) << (bs ## __bf)) 替换BIT_MASK(__bf) 得出
((MCDR2) = ((MCDR2) & ~((((1U << (bwMCDR2_ADDRESS)) - 1) << (bsMCDR2_ADDRESS)) )) |(((RegisterNumber) << (bsMCDR2_ADDRESS)) & ((((1U << (bwMCDR2_ADDRESS)) - 1) << (bsMCDR2_ADDRESS)))))
3.然后使用
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17得出
((MCDR2) = ((MCDR2) & ~((((1U << (4)) - 1) << (17)) )) |(((RegisterNumber) << (17)) & ((((1U << (4)) - 1) << (17)))))
其中((((1U << (4)) - 1) << (17)) )算出二进制数"1111 0000 0000 0000 0000 0",
~((((1U << (4)) - 1) << (17)) )则为"0000 1111 1111 1111 1111 1"
即
MCDR2 = ((MCDR2) & "0000 1111 1111 1111 1111 1" ) | ((RegisterNumber << 17) & "1111 0000 0000 0000 0000 0").
最后应该是MCDR2=(MCDR2的低17位,加上RegisterNumber的低四位最后MCDR2的高4位)
解释:2:
对于下列宏进行分析:
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESSBIT_MASK(MCDR2_ADDRESS)
#define BIT_MASK(_bf)((1U<<(bw##_bf))-1)<<(bs##_bf)
#define SET_BITS(_dst, _bf, _val)\
(_dst)= (((_dst)&~(BIT_MASK(_bf))) |(((_val)<<(bs##_bf))&(BIT_MASK(_bf))))
// 使用形式:SET_BITS(MCDR2,MCDR2_ADDRESS, RegisterNumber)
宏BIT_MASK:形成bwMCDR2_ADDRESS个1位及bsMCDR2_ADDRESS个0位的二进位串,即(bwMCDR2_ADDRESS+ bsMCDR2_ADDRESS)位地址的高bwMCDR2_ADDRESS为1的掩码。在此例中,bmMCDR2_ADDRESS = 1 1110 0000 0000 0000 0000。
工作原理:
(1U<<(bw##_bf))-1:将1左移bwMCDR2_ADDRESS位,并-1,当为4时,即(B1 0000 – 1) = 1111。
((1U<<(bw##_bf))-1)<<(bs##_bf):左移bsMCDR2_ADDRESS位,补0,即1 1110 0000 0000 0000 0000。
宏SET_BITS:将_dst地址的低bsMCDR2_ADDRESS(此例为17)与_val组成新地址。
若_dst=1 0010 1001 1100 0101 0011,_val = 0011,则_dst将形成新的地址:
0 0110 1001 1100 0101 0011。
工作原理:
(_dst)&~(BIT_MASK(_bf)):将掩码取反,与_dst相与,即取低bsMCDR2_ADDRESS位。
(_val)<<(bs##_bf)):将_val左移bsMCDR2_ADDRESS位,_val对应高bwMCDR2_ADDRESS位。
((_dst)&~(BIT_MASK(_bf))) |(((_val)<<(bs##_bf))&(BITMASK(_bf))):即将上两值或运算,取_val低bsMCDR2_ADDRESS位,取_val高bwMCDR2_ADDRESS位。
作用:SET_BITS可用于更新(bwMCDR2_ADDRESS+ bsMCDR2_ADDRESS)位IP地址的网络编号。
源码如下所示:
#include "stdio.h"
#include <stdlib.h>
#include "conio.h"
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)
#define BIT_MASK(_bf) ((1U<<(bw##_bf))-1)<<(bs##_bf)
#define SET_BITS(_dst, _bf, _val)\
(_dst)= ( ((_dst)&~(BIT_MASK(_bf))) | (((_val)<<(bs##_bf)) & (BIT_MASK(_bf))) )
/*使用形式:SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber)*/
void main()
{
unsigned dst = 0x1ffff; /* 1 1111 1111 1111 1111*/
unsigned regnum = 0x8; /* 1000 */
printf("%x\n", BIT_MASK(MCDR2_ADDRESS)); /*0x1e0000, 即: 1 1110 0000 0000 0000 0000*/
SET_BITS(dst, MCDR2_ADDRESS, regnum);
printf("%x\n", dst);/*11ffff,即: 1 0001 1111 1111 1111 1111*/
}