C 对于一点掩蔽问题,什么是好的解决方案?

C 对于一点掩蔽问题,什么是好的解决方案?,c,embedded,bit-manipulation,bitmask,C,Embedded,Bit Manipulation,Bitmask,问题 我希望在不影响其他位的情况下,将位组合更改为其他组合 在此组合中,某些位必须未设置或设置 问题:什么是最好的掩蔽解决方案。特别是对于未设置的掩蔽。我 例如:更改位[3:0]>0b1011(数据) 目的位[3:0]->0b0110 让我分享一下我的尝试: 创建了一个未设置的掩码:1的0b1001-->[1111]0110的补码(将不关心的位更改为1) 已创建掩码:0b0110 有了这两个掩码,我可以使用逐位运算 int data = 0xB; /*0b1011 (0x

问题

  • 我希望在不影响其他位的情况下,将位组合更改为其他组合
  • 在此组合中,某些位必须未设置设置
问题:什么是最好的掩蔽解决方案。特别是对于未设置的掩蔽。我

例如:更改位[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*/

简单的答案是肯定的,你用一个掩码清除你想清除的位,另一个掩码设置你想设置的位。但是,有时,根据掩码和数据的使用方式以及它们代表的内容,您需要了解一些隐藏的硬件级别的事情

如果您只想将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和
掩码通常可以清除您关心的所有位,这样您就不需要两个特殊的掩码。

您要的是通用解决方案吗?或者,为了知道除了您针对这些设定值提出的解决方案之外,是否存在其他(更好的)解决方案?您所描述的正是它通常是如何完成的。您的编译器将完成其余的工作。当位旋转时,微控制器(如AVR)上非常常见的模式。像
PORTB |=1这样的行定义最佳。只要您不担心原子性,以上方法就非常有效。如果是,则需要采取一些额外的步骤,但掩码代码基本保持不变。此外,您的编译器还应该能够确定您的系统是否有更好的汇编操作码,以便仅从代码中执行您想要的操作。如果您需要将位同时更改为关闭和打开,则需要两个掩码。一个要清除,一个要设置。是的,我的主要问题是关于寄存器位操作,但在我尝试之前,我首先想了解这个问题。你可能已经用较少的语言说了,但它非常重要。如果您正在使用指针魔术,这样您就有一个指向硬件寄存器myreg的指针,当您使用它时,它实际上会接触到寄存器myreg&=~0x7;myreg |=0x2;您可能已经更改了这些位,然后再次更改它们,您希望创建一个副本temp=myreg;温度&=~0x7;温度|=0x2;myreg=温度。因此,请理解访问方法。如果这只是一个变量中的数据,那么正如前面所述,正如您所计算的,您需要一个and到零位和一个or来设置位。