使用bitmask和if语句

时间:2015-04-23 20:21:19

标签: c switch-statement bitmask

我试图允许多个案例在switch语句中运行。我有一个位掩码如下:

#define SHOOT_ROCKET 2 << 16
#define MOVE_FORWARD 3 << 16

后来,我做了

switch (int game_action)

我有

case SHOOT_ROCKET:
  result = fire_weapon(rl);

我不想“打破”,因为我想要多种行动的可能性。但我正在返回一个名为&#39; result&#39;的值。我将它存储为变量并在最后返回。我可以告诉其他一些情况:即使他们不应该发表声明,因为结果不断变化,如果我加上休息,则不会发生声明;

处理此问题的最佳方法是什么?

更新:我已经被告知要这样做。

我改变了我的&lt;&lt; bitmasks所以他们现在从1开始。

我遇到了一个奇怪的错误

if (game_action->action & SHOOT_ROCKET)
{
    game_action->data=5;
}
if (game_action->action & MOVE_FORWARD)
 {
    game_action->data=64;
}

当我打算将多个if评价为真时,我并不担心game_action会被覆盖

然而:即使我只是尝试射击火箭,似乎MOVE_FORWARD正在发生!

game_action通常是一个无效指针,所以这就是它在函数中的设置方式:

game_action = (game_action) *game_action_ptr;

我已经用

验证了位掩码是否正确
printf("%d", game_action->action >> 16) which prints 2.

那么为什么&#39; 3&#39; (前进)发生在我只想射击火箭的时候?

2 个答案:

答案 0 :(得分:0)

请更新您的问题。

  

那么为什么&#39; 3&#39; (前进)发生在我只想射击火箭的时候?

您要看的第一件事是

#define SHOOT_ROCKET 2 << 16
#define MOVE_FORWARD 3 << 16

并考虑评估的内容。它将评估以下二进制数字(Python对于这种东西很方便,0b只是一个前缀,意味着二进制文件正在跟随):

>>> bin(2 << 16)
'0b100000000000000000'
>>> bin(3 << 16)
'0b110000000000000000'

所以你看到你在#define中使用了两次(退役忍者已经指出了这一点)。这意味着,如果将game_action->action设置为位2 << 161的任何位置,则两个ifs将评估为true,因为两个#define都将该位设置为1

  

使它们相互排斥,我应该做2,4,8,而不是1,2,3,4?

如果您想轻松跟踪使用哪些位,您可以使用2的幂(1,2,4,8,16等),例如#define MOVE_FORWARD 4(我忽略了你拥有的<< 16,如果你愿意,你可以添加它,或者你可以将1移动一个可变位数,这两个都会导致相同的二进制数:

#define MOVE_LEFT 1 << 0
#define MOVE_RIGHT 1 << 1
#define MOVE_UP 1 << 3
#define MOVE_DOWN 1 << 4

有些合法的情况是位掩码需要设置多个位,例如检查是否设置了多个位中的任何一位:

#define MOVE_LEFT ... (as above)
#define SHOOT_ROCKET 1 << 5
#define SHOOT_GUN 1 << 6
//...
#define ANY_MOVEMENT 0xF
#define ANY_WEAPON_USE 0xF << 4

然后检查:

if (action & ANY_MOVEMENT) { ... }
if (action & ANY_WEAPON_USE) { ... }

答案 1 :(得分:0)

放置parens&#39;(&#39;&#39;)&#39;在值部分(2&lt;&lt;&lt;&lt; 15)类型的值附近,因此文本替换不会引入错误。

即。这个:

'if( (&game_action->action & MOVE_FORWARD) == MOVE_FORWARD)' 

成为

'if( (&game_action->action & 2 << 16) == 2 << 16)' 

注意发布的代码缺少左边的paren,我添加了。

&#39;&amp;&#39;具有更高的优先级&#39;&lt;&lt;&lt;&lt;&lt;&#所以它(有效地)变成

'if( ( (&game_action->action & 2) << 16) == 2 << 16)' 

&#39;&amp;&#39;完成2而不是2 <&lt; 16&lt; / p>