Advertisement

Bitwise operators and logic...

Started by November 09, 2000 04:58 PM
16 comments, last by HBringer 24 years, 1 month ago
I''m sure this can be done using a switch / case statement

3 different state switchs ... 8 options (0-7)

  #define S_A 1#define S_B 2#define S_C 4int state = S_A | S_B;switch (state){case S_A:	printf( "S_A" );	break;case S_B:	printf( "S_B" );	break;case S_A | S_B:	printf( "S_A | S_B" );	break;case S_C:	printf( "S_C" );	break;case S_A | S_C:	printf( "S_A | S_C" );	break;case S_B | S_C:	printf( "S_B | S_C" );	break;case S_A | S_B | S_C:	printf( "S_A | S_B | S_C" );	break;default:	printf( "NONE / ERROR" );	break;}  


I''ve just checked the above code and it works, as long as you want to sit and go though all of your options (valid and invalid).

The output of the program was S_A | S_B. Tested on a linux system using pure ANSI C code.
When I find my code in tons of trouble,Friends and colleages come to me,Speaking words of wisdom:"Write in C."My Web Site
It should be noted that you can use a switch statment because all of the bits are also tranlate into some integer value.

So if you have

#define STATE_A 1
#define STATE_B 2
#define STATE_C 4

int statevals;

statevals=STATE_A|STATE_B;

then the value stored in statevals is 3.

Note that doing a case (STATE_A&STATE_C) is the same as saying case 5.

Advertisement
Ooops that last line should be
case (STATE_A|CASE_C) is the same as case 5
As a purely random thing... (someone tell me if that XOR operator is wrong, please) You could possibly save a tiny bit of speed in your code turning off a switch with this, but only if you know it''s on...

//invert a switch
SomeStateVar ^= SomeSwitch;

--Tr][aD--
--Tr][aD--
quote: Original post by HBringer

Thanks to both of you though!

Gunnar - and some of your "&" signs need to be single; not doubled up, since its bitwise comparisons :-)

Thanks again!

--HB


yeah, I saw that. sometimes I forget to think about what I''m writing
You cannot do it with a switch statement. Look at this piece of code and try it if you want. I know the indents are gone, but you''ll have to live with that

Anyway, I define 3 states and perform a switch where all of the states are set. If you want to check for bits all states in the following code should be true since all bits (states) are set. But you will see that "NONE" message box. Why? Because "case STATE_1 | STATE_2" means "x == (STATE_1 | STATE_2)". In this case x would be (STATE_1 | STATE_2 | STATE_3) and that is NOT true in any of the cases.

So, you cannot use switch.

- Benny

#include

#define STATE_1 1
#define STATE_2 2
#define STATE_3 4

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
switch( STATE_1 | STATE_2 | STATE_3 )
{
case STATE_1:
::MessageBox( NULL, "STATE_1", NULL, MB_OK );
break;
case STATE_1 | STATE_2:
::MessageBox( NULL, "STATE_1 | STATE_2", NULL, MB_OK );
break;
case STATE_1 | STATE_3:
::MessageBox( NULL, "STATE_1 | STATE_3", NULL, MB_OK );
break;
default:
::MessageBox( NULL, "NONE", NULL, MB_OK );
break;
}

return 0;
}
-Benny-
Advertisement
Benny''s incorrect. You can use a switch. He didn''t include a case for all three set.

The problem here is that state is a bitmask, and so if you want to switch on it, you have to find the boolean equivalent of every state you''re looking for. This is much easier to explain if you have a background in digital logic.

If you have 3 bits, there are eight possible states (2^3). Since switch is an equivalency operation, it checks that your argument is EXACTLY equal to each switch branch. If you''re familiar with Karnaugh maps, this means that each switch branch represents a single cell, not any group.

Example:
(state & STATE_A) 

This statement is true when the STATE_A bit is set, regardless of the other bits.

However, this:
switch (state)  STATE_A: 

..is completely different. This label will be reached iff (if-and-only-if) state == STATE_A. If you wanted to make an equivalent switch statement to (state & STATE_A), you have to include all possible minterms:
switch (state)  STATE_A:   STATE_A | STATE_B:   STATE_A | STATE_C:   STATE_A | STATE_B | STATE_C:    // now you put the code to execute if (state & STATE_A) 

If you wanted to code a switch if STATE_A and STATE_C are set, you have to do this:
switch (state)  STATE_A | STATE_C:  STATE_A | STATE_C | STATE_B:    // put the code to execute if STATE_A and STATE_C are set,    // regardless of the STATE_B bit   


I don''t know why anybody would want to do this. You lose a lot of the flexibility of bitmasks because this kind of flow:
if (state & STATE_A)  // do somethingif (state & STATE_B)  // do something 

...would require 2 different switch statements, each with 4 cases that go to the same command. But it''s legal. It''s possible. I think it might even compile to the same code. So again, I don''t know why anybody would want to go that way.
I''ll make it simpel. Or maybe not.

The states are defined as STATE_1 = 1, STATE_2 = 2 and STATE_3 = 4.

x = STATE_1 | STATE_2 | STATE_3; // x = 0111 (binary)

Let''s say you want to check if STATE_1 and STATE_2 is set for x. Doing it with if would look like this:

if( x & (STATE_1 | STATE_2) == (STATE_1|STATE_2) )
// The left of ''=='' is "0111 & (0001 | 0010)" which means "0111 & 0011" and that in turn means "0011"
// The right of ''=='' is simply 0011 (0001 | 0010)
// The gives us, 0011 == 0011 which is true
// I would have used "if( x & STATE_1 && x & STATE_2 )" for doing this though, this was just an example

// Here x still is 0111
switch( x )
{
case (STATE_1 | STATE_2): // This is the same as "case 0011:" 0011 is binary, just so there will be no misunderstandings
// Now switch will compare x with the case by using something similiar to "if( x == y )" which would
// give us:
// if( 0111 /*binary value of x*/ == 0011 /*binary value of the case*/ )
// As you can see this is not true. And yes, I do know that you can''t use binary values like that. It was
// just for the example
}

Then you say that "Benny''s incorrect. You can use a switch. He didn''t include a case for all three set.". Now, why didn''t I do that?

1) I wanted to show that you cannot check for, as in my example, two bits only. Of course you can include all possible cases in that switch statement. But if you have 32 bits that can be set. I don''t care to count the number of possible cases but I''m sure you don''t want to sit there and write them all -- Use if instead.

2) If included a check for STATE_1 it would look something like this:

case STATE_1:
case STATE_1 | STATE_2:
case STATE_1 | STATE_3:
case STATE_1 | STATE_2 | STATE_3:

Then there''s one check like that for STATE_2 and STATE_3 plus (STATE_1 | STATE_2), (STATE_1 | _STATE_3), (STATE_2 | STATE_3) and finally (STATE_1 | STATE_2 | STATE_3).

3) Ok, it''s POSSIBLE to do it. But at the same time it''s not, not if you want to do something else than write cases at least. But! It is still not possible to perform a bitwise comparison in a case statement. It is possible to twist my words and missunderstand a thing or two to prove me wrong

Try doing "if( x & (STATE_1 | STATE_2) )" with "case (STATE_1 | STATE_2):" and you will fail every time.

Well, that''s it about that. I''m going to read Winter''s Heart now

-Benny-

This topic is closed to new replies.

Advertisement