C-一个掩盖问题的好解决方案是什么?



问题

  • 我想将一些组合更改为其他组合,而不会影响其他位。
  • 在此组合中,某些位必须为 unset set

问题:最好的 basking解决方案是什么。特别是对于 unset basking.i

一个示例:更改位[3:0] -> 0b1011(数据) 目的位[3:0] -> 0b0110

让我分享我尝试的东西:

  • 创建一个不设置的蒙版:1的补充0b1001-> [1111] 0110(要将不贴心的位更改为1)
  • 创建蒙版:0B0110

,使用这两个口罩,我可以使用位于位操作。

int data = 0xB;         /*0b1011 (0xb) -> 0110 (0x6)*/
int umask = 0x9;        /*unset mask 0b1001*/
int smask = 0x6;       /*Set Mask 0b0110*/
data &= ~umask;        /*Unset the bits what needs without affecting other*/
data |= smask;         /*Set the bits what needs to be set*/

简单的答案是肯定的,您使用1个掩码清除要清除的位,而另一个则设置要设置的位。但是,有时候,您需要了解隐藏的硬件级别,具体取决于掩盖和数据的使用以及它们代表的内容。

如果您只想将4位设置为一个值:

val &= ~(0xf); // This only clears the low 4 bits, preserving the rest.
assert((new4BitMaskvalue & ~0xf) == 0); // Make sure new mask only plays with low 4 bits.
val |= new4BitMaskvalue;  // or new mask

您在技术上清除了一些额外的位,但这使您只能在清除时使用一个通用面具。您也可以像这样清除确切的位,但这可能不是必需的。

通常,如果您在CPU支持的内存单元大小中立即设置所有字段,则可以分配整个值并保存步骤。(U8/U16/U32/U64/等)

现在,"有趣"部分。如果这些位代表实际的硬件寄存器,则可能无法设置这样的整个字段,因为它可能会引起令人兴奋的行为。也许这是一个中断启用寄存器。如果是这样,不需要清理和设置的清除和重置位会引起意外的副作用。另外,寄存器通常只读或写,在这里您需要谨慎掩饰的方式,甚至可能被迫一次设置或清除一个单个碎屑。

简而言之,是的,您通常至少需要2个值才能清除并设置位。通常可以允许第一个not and掩码清除您关心的所有位,以便您不需要2个特殊的口罩。

最新更新