第1个回答 2012-10-02
在#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个回答 2012-10-02
你这上面三行是宏替换,其实也就是预处理时预处理器会把左边的字符串替换成右边的字符串,下面两个是带参数的宏替换,也就类似于函数。解决此类复杂宏替换的最好办法就是用你编译器对应的命令查看预处理输出结果,这方面百度一下就有一大把。##是一个特殊的宏替换,叫做粘贴符号,可能比较难懂,具体的可以参考《windows程序设计》P41,引用如下:
现在开始讨论字串文字中的L 问题。
如果定义了_UNICODE 识别字,那么一
个称作__T 的宏就定义如下:
#define __T(x) L##x
这是相当晦涩的语法,但合乎ANSI C 标准的前置处理器规范。那一对井字
号称为「粘贴符号(token paste)」,它将字母L 添加到宏引数上。因此,
如果宏引数是"Hello!",则L##x 就是L"Hello!"。本回答被网友采纳