C语言 如何将掩码位设置为指定的数字?



我没能在Google上找到这个问题的答案,我也没有更好的搜索想法。如果我有一个2字节的数字,一个掩码和第三个数字,我如何用第三个数字替换掩码位。例如,如果我有0xABCD,掩码0x0F00和第三个数字4 -我想用4取代B以获得A4CD。换句话说,我希望能够用另一个任意数字的比特替换掩码选择的任意比特(我们假设替换比特的数字适合-即,如果我掩码5位,替换这5位的数字需要5位或更少的比特来表示。)

目标是假设value不超过目标范围,将mask选择的number的位替换为value的位,并进行适当的移位。

屏蔽目标位很容易:number &= ~mask;可以简单地实现。

棘手的部分是将value向左移动mask中低于设置位的零位数。您可以为此编写一个循环。

下面是一个简单的实现:

unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
// assuming mask != 0
number &= ~mask;
while (!(mask & 1)) {
value <<= 1;
mask >>= 1;
}
return number | value;
}

你可以这样计算移位值作为乘法器:从mask中减去1将其所有的0低位位设置为1,或者将该值与mask结合将所有低位位设置为1,与mask结合将产生仅设置低位位的掩码。在这个掩码上加上1,得到2的幂,乘以value来移动它的位置。如果mask的低阶位中没有0位,

aschepler所注释的,(A ^ (A | B)) == (~A & B),因此表达式((mask ^ (mask | (mask - 1))) + 1)可以简化为(((mask - 1) & ~mask) + 1)

Falk hffner提供了一个优雅的简化:(((mask - 1) & ~mask) + 1)就是mask & -mask

下面是使用此技巧的无分支版本:

unsigned set_bits(unsigned number, unsigned mask, unsigned value) {
return (number & ~mask) | (value * (mask & -mask));
}

使其成为内联函数可以帮助编译器为常量掩码值生成最佳代码。

最新更新