#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
#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()
位操作詳解
我們先來看看位運算操作符 按位與 按位或 按位異或 按位取反 按位右移 按位左移 1 按位與 從概念上來講,就是將參與運算的兩個分量對應的每一位來做邏輯與運算,若兩者都為真 等於1 則結果才為真 等於1 否則都為假 等於0 即 1 1 1 1 0 0 0 1 1 0 0 0 這裡我們先來看看那乙個8...
位運算操作詳解
在計算機中所有資料都是以二進位制的形式儲存的。位運算其實就是直接對在記憶體中的二進位制資料進行操作,因此處理資料的速度非常快。在實際程式設計中,如果能巧妙運用位操作,完全可以達到四兩撥千斤的效果,正因為位操作的這些優點,所以位操作在各大it公司的筆試面試中一直是個熱點問題。基本的位操作符有與 或 異...
位運算操作符詳解二
位運算是指進行二進位制的運算。在系統軟體中,常需要處理二進位制位的問題。例如,將乙個儲存單元中的各二進位制位左移或右移一位,兩個數按位相加等。c語言提供位運算的功能。運算子 含義 按位與 按位或 按位異或 取反 左移 右移 說明 位運算子中,除了 取反以外,均為二目 元 運算子,即要求兩側各有乙個運...