0

I am trying to allow multiple cases to run in a switch statement. I have a bitmask as follows:

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

Later, I do

switch (int game_action)

and I have

case SHOOT_ROCKET:
  result = fire_weapon(rl);

I don't want to 'break', because I want possibility of multiple actions. But I am returning a value called 'result'. I store this as a variable and return at the end. I can tell other case: statements are running though even when they shouldn't because result keeps getting changed and doesn't if I add break;

What is the best way to deal with this?

Update: I've been told to do if instead.

I changed my << bitmasks so they start at 1 now.

I am experiencing a weird bug

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

I am not concerned about game_action being overwritten when I intend for multiple if's to evaluate to true

However: it seems MOVE_FORWARD is happening even if I only try and shoot a rocket!

game_action is a void pointer normally, so this is how it's setup in the function:

game_action = (game_action) *game_action_ptr;

I have verified the bitmask is correct with

printf("%d", game_action->action >> 16) which prints 2.

So why is '3' (the move forward) happening when I am only trying to shoot a rocket?

Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
user3526827
  • 153
  • 1
  • 1
  • 9

2 Answers2

0

Please do update your question.

So why is '3' (the move forward) happening when I am only trying to shoot a rocket?

The first thing you want to look at is

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

and think what that evaluates to. It will evaluate to the following binary numbers (Python is handy for this kind of stuff, 0b is just a prefix that means binary is following):

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

So you see that you use one bit twice in your #defines (Retired Ninja already pointed this out). This means that if game_action->action is set to anything where the bit 2 << 16 is 1, both of your ifs will evaluate to true, because both #defines have that bit set to 1.

to make them mutually exclusive, should i do 2, 4, 8, instead of 1,2,3,4?

If you want to easily keep track of which bits are used, you can either use powers of two (1,2,4,8,16, etc), e.g. #define MOVE_FORWARD 4 (I'm ignoring the << 16 you have, you can add that if you want), or you can shift a 1 by a variable number of bits, both result in the same binary numbers:

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

There are legitimate cases where bitmasks need to have more than one bit set, for example for checking if any one of several bits are set:

#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

and then check:

if (action & ANY_MOVEMENT) { ... }
if (action & ANY_WEAPON_USE) { ... }
m01
  • 9,033
  • 6
  • 32
  • 58
0

place parens '(' ')' around the value part (2<<15) kind of values so there is no errors introduced by the text replacement.

I.E. this:

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

becomes

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

Note the posted code is missing a left paren, which I added.

Where the '&' has a higher Precedence the '<<' so it (effectively) becomes

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

where the '&' is done to the 2 and not to the 2<<16

user3629249
  • 16,402
  • 1
  • 16
  • 17