2

是否有类似于:
if((bitmap & BIT_WATER) && (bitmap & BIT_FIRE)) bitmap &= ~BIT_FIRE

if(bitmap & BIT_WATER) bitmap &= ~BIT_FIRE

在仅使用按位运算的单个语句中,不需要比较(如果)?

我的意思是,如果两个完全相反的标志被设置为明确的一个。

4

6 回答 6

2

您可以避免bitmap & BIT_FIRE在第一种情况下,因为bitmap &= ~BIT_FIRE;不会对未设置的bitmapif做任何事情。BIT_FIRE

没有以任意方式“设置位 X,如果设置位 Y”。

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

于 2013-09-13T00:39:59.707 回答
2

可能过早的优化,但你可以做

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 并让编译器优化它......

于 2013-09-13T01:16:00.327 回答
1

如果你需要写一个通用的,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);
于 2013-09-13T03:03:18.173 回答
1

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

bitmap &= ~(((bitmap >> SHIFT_WATER) & 1) << SHIFT_FIRE)
于 2013-09-13T19:55:39.807 回答
1

将我的评论推广到答案。请注意,它使用乘法,但也许它对您仍然有用(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
于 2013-09-13T01:20:30.193 回答
0

假设 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 之间的方向和增量。填写适当的增量。

于 2013-09-13T14:33:50.063 回答