位操作的詳解

2021-07-09 09:09:30 字數 3949 閱讀 8895

#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語言提供位運算的功能。運算子 含義 按位與 按位或 按位異或 取反 左移 右移 說明 位運算子中,除了 取反以外,均為二目 元 運算子,即要求兩側各有乙個運...