是否有类似于:
if((bitmap & BIT_WATER) && (bitmap & BIT_FIRE)) bitmap &= ~BIT_FIRE
或
if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE
在仅使用按位运算的单个语句中,不需要比较(如果)?
我的意思是,如果两个完全相反的标志被设置为明确的一个。
是否有类似于:
if((bitmap & BIT_WATER) && (bitmap & BIT_FIRE)) bitmap &= ~BIT_FIRE
或
if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE
在仅使用按位运算的单个语句中,不需要比较(如果)?
我的意思是,如果两个完全相反的标志被设置为明确的一个。
您可以避免bitmap & BIT_FIRE
在第一种情况下,因为bitmap &= ~BIT_FIRE;
不会对未设置的bitmap
if做任何事情。BIT_FIRE
没有以任意方式“设置位 X,如果设置位 Y”。
当然,如果你知道BIT_FIRE
比 高一点BIT_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 的幂)。您可能还希望位图是无符号的,以确保编译器可以轻松地将其优化为一个移位、两个按位与和一个补码。
当然,一个好的编译器会将您的原始代码优化为相同的 4 条指令而没有分支。
编辑
当然,我意识到上面是不正确的——只有在 BIT_FIRE > BIT_WATER 时才有效。
所以只要坚持原来的 if 并让编译器优化它......
如果你需要写一个通用的,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)
将我的评论推广到答案。请注意,它使用乘法,但也许它对您仍然有用(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
假设 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 之间的方向和增量。填写适当的增量。