一种直接根据掩码转位的方法

A direct way to turn bits according to mask

假设我们有一个字节 B 和一个掩码 M 使得掩码中的一位为 1 或 0 而其他位为 0,(假设我们知道哪一位是是,它可以是任何位,但为简单起见,它是 LSB)。我们希望 B 中的相同位与 M 中的相同位具有相同的值。

例如如果B=1111M=0000那么我们希望运算后有B=1110,但是如果MM=0001那么B 本来是 B=1111.

我基本上是在问如何实现根据这个真理生成的布尔函数table:

old new result
0   0   0
0   1   1
1   0   0
1   1   1

所以 result 将是:

a=old, b= new
result=a'b+ab

在 C 中执行 B = ~B&M | B&M; 似乎不起作用...

我可能可以使用条件语句来做到这一点,但是没有它们就必须有一种方法。

另一个例子: 如果我们关心第二位,如果B=0001M=0010那么操作的结果将是0011。但是如果 MM=0000 那么操作的结果是 0001.

我知道如何设置清除和切换位,这不是我要问的。

它不能作为布尔函数实现,因为您要使用的运算符是按位的,因此操作数是多位的。但是您可以合并一些移位来适应这一点:

#define BIT_NUMBER   3  // For example

B &= ~(1 << BIT_NUMBER); // Zero out the bit
B |= M << BIT_NUMBER; // Set to M's bit value

您需要指定您关心的位的偏移量(例如index):

char AssignBit(unsigned char byte, unsigned char mask, int index)
{
    unsigned char cleared = byte & ~(1 << index);
    unsigned char assigned = cleared | mask & (1 << index);
    return assigned;

    // or simply:
    return byte & ~(1 << index) | mask & (1 << index);

    // if it is guaranteed that at most one bit is set in mask, this also works:
    return byte & ~(1 << index) | mask;
}

如何将第 n 位更改为 x:

number ^= (-x ^ number) & (1 << n);

(摘自)

For example if B=1111, M=0000 then we want to have after the operation B=1110

问题是你没有指定M中的哪个位是有效的,并且无法从M的值中确定有效位。


您实际上需要三个数量,字节 B、值 V(您称之为 M)和掩码 M(您的问题中缺少).

下面是结合了这三者的代码:

result = (B & ~M) | (V & M);

如果我没理解错的话,您想将 B 中的单个位设置为 M 中该位的值,而您不关心 B 中的先前值是什么。在这种情况下,M 并不是真正的面具;您的掩码由位数给出。所以你会做类似

的事情
unsigned mask = (1<<BITNUM);
unsigned result = (~mask & B) | (mask & M)

如果是 LSB,则 BITNUM = 0。