如何使用c替换位域中的位而不影响其他位

Uni*_*orn 18 c bit-manipulation

我想在32/64位数据字段中替换位/位(大于1)而不影响其他位.例如:

我有一个64位寄存器,其中第5位和第6位可以取值0,1,2,3.

5:6    
0 0
0 1
1 0
1 1     
Run Code Online (Sandbox Code Playgroud)

现在,当我读取寄存器时,我得到值0x146(0001 0 10 0 0110).现在我想将第5位和第6位的值更改为01.(现在它是10,十进制是2,我想要在没有其他位受到影响的情况下将其替换为1 e 01)并仅在修改了位5和6的情况下写回寄存器(因此在更改后变为126)

我试过这样做

reg_data=0x146
reg_data |= 1 << shift   (shift in this case is 5)
Run Code Online (Sandbox Code Playgroud)

如果我在位5和6处执行该值将变为11(0x3)而不是01(0x1),这是我想要的.

  • 我如何进行读/修改/写?
  • 如何在不影响使用C的字段的整个数据的情况下,仅替换32/64位字段中的某些位/位?

设置一点是可以的,但不止一点,我发现它有点困难.

任何建议都非常感谢.

vy3*_*y32 26

你为什么不使用位掩码?有点像:

new_value = 0, 1, 2 or 3  // (this is the value you will set in)
bit_mask = (3<<5)         // (mask of the bits you want to set)
reg_data = (reg_data & (~bit_mask)) | (new_value<<5)
Run Code Online (Sandbox Code Playgroud)

这保留了旧位和OR的新位.


Ama*_*9MF 10

reg_data &= ~( (1 << shift1) | (1 << shift2) );
reg_data |= ( (1 << shift1) | (1 << shift2) );
Run Code Online (Sandbox Code Playgroud)

第一行清除(shift1,shift2)的两位,第二行设置它们.

  • +1.此外,如果你知道它们是相邻的,它会变得更简单:例如,在这种情况下,`reg_data = reg_data&(〜(3 << 5))| (1 << 5)` (3认同)

pho*_*xis 7

这是一个通用的过程,它作用于一个长数组,考虑到它是一个长位域并分别寻址每个位的位置

#define set_bit(arr,x) ((arr[(x)>>3]) |= (0x01 << ((x) & 0x07)))
#define clear_bit(arr,x) (arr[(x)>>3] &= ~(0x01 << ((x) & 0x07)))
#define get_bit(arr,x) (((arr[(x)>>3]) & (0x01 << ((x) & 0x07))) != 0)
Run Code Online (Sandbox Code Playgroud)

简单地,索引使用索引的低3 btis来识别char数组的每个位置内的8个不同的位位置,并且上部的剩余位地址用于表示由所表示的位的阵列位置x.希望这可以帮助.

编辑1: 要设置一个位,您需要将目标字与该特定位位置为1的另一个字或与目标的所有其他字相对应.其他位置的所有0都确保目标中的现有1是在OR期间,并且特定位置中的1确保目标在该位置获得1.如果我们有掩码= 0x02 = 00000010(1字节),那么我们可以对任何单词进行OR运算以设置该位pos

target = 1 0 1 1 0 1 0 0
OR       + + + + + + + +
mask     0 0 0 0 0 0 1 0
         ---------------
answer   1 0 1 1 0 1 1 0
Run Code Online (Sandbox Code Playgroud)

要清除一点,您需要将目标字与该特定位位置为0的另一个字进行AND运算并且总共为1.在所有其他位位置中的所有1确保在AND期间,目标保持其在那些位置中的0和1,并且要清除的位位置中的0也将在目标字中设置该位位置0.如果我们有相同的掩码= 0x02,那么我们可以准备这个掩码来清除〜掩码

mask  = 0 0 0 0 0 0 1 0 
~mask = 1 1 1 1 1 1 0 1
AND     . . . . . . . .
target  1 0 1 1 0 1 1 0
        ---------------
answer  1 0 1 1 0 1 0 0
Run Code Online (Sandbox Code Playgroud)