如果设置了另一个位,则清除位

Clear bit if another is set

本文关键字:清除 另一个 设置 如果      更新时间:2023-10-16

是否有类似于:

if((bitmap & BIT_WATER) && (bitmap & BIT_FIRE)) bitmap &= ~BIT_FIRE
if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE

在仅使用按位运算的单个语句中,无需比较 (if)?

我的意思是,如果两个旗帜,每个旗帜都与另一个完全相反,被明确设置其中一个。

在第

一种情况下,您可以避免bitmap & BIT_FIRE,因为如果未设置BIT_FIRE bitmap &= ~BIT_FIRE;则不会对bitmap执行任何操作。

没有任意方式的"如果设置了位 Y,则设置位 X"。

当然,如果你知道,比如说,BIT_FIREBIT_WATER高一点,你可以做bitmap &= ~(BIT_WATER << 1),这将清除"比BIT_WATER高一点"。

可能过早优化,但你可以这样做

bitmap &= ~((bitmap & BIT_WATER) * (BIT_FIRE/BIT_WATER)) & ~((bitmap & BIT_WATER) * (BIT_WATER/BIT_FIRE))

只要BIT_FIRE和BIT_WATER是单比特(2的幂)。 您可能还希望位图是无符号的,以确保编译器可以轻松地将其优化为单个移位、两个按位 and 和一个补码。

当然,一个好的编译器会优化你的原始代码,直到相同的 4 条指令,没有分支。

编辑

当然,我意识到上述内容是不正确的 - 只有在BIT_FIRE> BIT_WATER时才有效。

所以只要坚持原来的if,让编译器优化它......

将我的评论提升为答案。请注意,它使用乘法,但也许它仍然对您有用(ideone.com 上的代码):

#include <iostream>
int main() 
{
 int long unsigned bitmap_with_water = 0xF300003F;
 int long unsigned bitmap_without_water = 0xF300000F;
 int long unsigned bit_fire = 0x03000000;
 int long unsigned bit_water = 0x00000030;
 bitmap_with_water &= ~(bit_fire * static_cast<bool>(bitmap_with_water & bit_water));
 bitmap_without_water &= ~(bit_fire * static_cast<bool>(bitmap_without_water & bit_water));
 std::cout << (void*)(bitmap_with_water) << "t" << (void*)(bitmap_without_water) << std::endl;
 return (0);
}

程序输出:

0xf000003f  0xf300000f

如果你需要写一个通用的clear_if_set(int test, int clear, int bitmap)那么这个答案是没有用的。

如果这是一个专门的功能,并且您知道从火到水的转换距离:

int water = bitmap & BIT_WATER;
int shifted = water << WATER_TO_FIRE_LSHIFT; // for example
bitmap &= ~shifted;

单行:

bitmap &= ~((bitmap & BIT_WATER) << WATER_TO_FIRE_LSHIFT);

如果使用位号而不是预移位掩码是可以接受的:

bitmap &= ~(((bitmap >> SHIFT_WATER) & 1) << SHIFT_FIRE)

假设BIT_WATER和BIT_FIRE不是同一个位,那么

的真值表

if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE

是(BIT_WATER、旧BIT_FIRE、新BIT_FIRE)

0 0   0
0 1   1
1 0   0
1 1   0

所以从一点的角度来看,这是

BIT_FIRE = (~BIT_WATER)&BIT_FIRE;
1 0   0
1 1   1
0 0   0
0 1   0

由于我不知道您的两个位之间的差距,因此这样的事情太过分了。

newbit = ((~(bitmap>>BIT_WATER_BIT))&(bitmap>>BIT_FIRE_BIT))&1;
bitmap&=~BIT_FIRE;
bitmap|=newbit<<BIT_FIRE_BIT;

假设我没有打错字...此外,如果您利用特定的位号并且不做一些通用的事情(将BIT_WATER位移位以降落在BIT_FIRE而不是将所有内容向右然后再次向左移动,我认为可以简化。 不过可能不会让它更简单。

如果位水位为 7,位火位为 3

bitmap = (((~(bitmap>>4))>>4)&(1<<3))&bitmap;

或者也许这个

bitmap = (((bitmap&(~BIT_WATER))^BIT_WATER)>>4)&bitmap;

其中>>4 是 BIT_WATER 和BIT_FIRE之间的方向和增量。 填写正确的增量。

相关文章: