Page 1 of 1

Bitwise Operators Flagging with bitwise operators Rate Topic: ***** 1 Votes

#1 sparkart  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 113
  • View blog
  • Posts: 688
  • Joined: 16-February 09

Posted 23 July 2009 - 03:27 PM

Flags usually have the boolean type, containing only two values: true(1) or false(0)

For instance you could have the following in a game:
bool fullscreen, useParticles, useBloom;



But wouldn't it be better if you had one variable that held all of the flags: int options;
By doing this, we can easily set our options like so:
//Turn on "fullscreen", "particle usage", "bloom effect"
options = FULLSCREEN | USEPARTICLES | USEBLOOM;



This can easily be achieved by using bitwise operators. Let me show you how.



Our flags will be represented by integers:
1  = Flag1
2  = Flag2
4  = Flag3
8  = Flag4
16 = Flag5



You may notice that we are using powers of 2. To better explain this, here is a binary representation:
1	 ->	 00000001
2	 ->	 00000010
4	 ->	 00000100
8	 ->	 00001000
16	->	 00010000



Doing this allows us to use each bit as a flag, for instance.... if we were to set Flag1(1), Flag2(2), Flag3(4) to on, our variable would have the following value (in binary format):
variable = 0x00000111;



Before we start, let me explain the OR(|) bitwise operator. Keep in mind that bitwise operators work at the binary level. OR evaluates two bits and will return 1 if either bit is 1.

For example:
int foo = 3 | 4;

To understand this, let us convert the numbers to binary format:
int foo = 00000011 | 00000100;

Here's what happens when you use the OR operator:
3 -> 00000011
4 -> 00000100
R -> 00000111 -> 7
Remember, it becomes 1 if either bit is 1.



So: foo = 3 | 4 = 7



Let us start by associating each value to a string representation. This can be achieved using enumerators.
enum Options
{
	Fullscreen=1, 
	Particles=2, 
	Bloom=4, 
	Flag4=8, 
	Flag5=16, 
	Flag6=32
}


Then we define the "options" variable:
Options myOptions;



Now to turn on flags:
//This code simply turns on the following flags:
//Fullscreen and Particles
myOptions = Fullscreen | Particles;





The next step is to check if a particular flag is turned on. But before we proceed you must understand how the AND (&) bitwise operator works. It isn't really that difficult. It is quite similar to the OR operator, but instead returns a 1 if both bits are 1.

Here is an example:
3 -> 00000011
4 -> 00000100
R -> 00000000 -> 0



Here is another example:
7 -> 00000111
4 -> 00000100
R -> 00000100 -> 4



The AND operator is needed for this routine as we will compare the option value with the flag mask:
Options equals 00000111		  Flags on: 1, 2, 3

Masks:
	Flag1 = 00000001
	Flag2 = 00000010
	Flag3 = 00000100



Checking if a flag is on is simple with the AND operator.
//Check if flag 4 is on: Flag4 mask: 00001000 (which is also: 8)
if (myOptions & 8)
	std::cout << "Flag 4 is on\n";




What makes it even more simple is the fact that we used enums:
if (myOptions & Fullscreen)
	std::cout << "Fullscreen is on\n";

if (myOptions & Particles)
	std::cout << "Using particles is on\n";

if (myOptions & Bloom)
	std::cout << "Bloom effect is on\n";





Here's what it could look like in a simple program:
#include <iostream>

enum Options
{
	Fullscreen=1,
	Particles=2,
	Bloom=4,
	Flag4=8,
	Flag5=16,
	Flag6=32
}

int main()
{
	Options gameOptions = Fullscreen | Bloom;
	int Running = 1;

	if (gameOptions & Fullscreen)
		WindowSetFullscreen();

	if (gameOptions & Bloom)
		TurnOnBloomShader();

	//Game Loop
	while (Running)
	{
		if (gameOptions & Particles)
			DrawParticles();
	}

	return 0;
}



I hope this tutorial was helpful and easily understood.

Is This A Good Question/Topic? 2
  • +

Replies To: Bitwise Operators

#2 born2c0de  Icon User is offline

  • printf("I'm a %XR",195936478);
  • member icon

Reputation: 180
  • View blog
  • Posts: 4,667
  • Joined: 26-November 04

Posted 26 July 2009 - 02:38 AM

Approved.
Changed boolean to bool as boolean is a Java keyword.
Was This Post Helpful? 0
  • +
  • -

#3 BetaWar  Icon User is offline

  • #include "soul.h"
  • member icon

Reputation: 1104
  • View blog
  • Posts: 6,913
  • Joined: 07-September 06

Posted 29 July 2009 - 02:58 PM

Okay, I have read the tutorial and have a few questions.

First off, what compiler are you using?

In Visual C++ 2008 Express Edition if I try this:

enum Options{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};

int main(){

	Options test;
	test = firstOption|second|third;

	return 0;
}


Based off of your example it gives me this error:

Quote

error C2440: '=' : cannot convert from 'int' to 'Options'


It doesn't however give me an error if I do this:
enum Options{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};

int main(){

	int test;
	test = firstOption|second|third;

	return 0;
}


Which I can then take further like so:

enum Options{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};

int main(){

	int test;
	test = firstOption|second|third;

	if(test & fourth){
		cout << "Fourth option is set on" << endl;
	}
	if(test & third){
		cout << "Third option is set on" << endl;
	}
	if(test & (firstOption | second)){
		cout << "First and Section options are set on" << endl;
	}
	if(test & firstOption){
		cout << "First option is set on" << endl;
	}
	if(test & second){
		cout << "Second option is set on" << endl;
	}

	return 0;
}


Getting the output:

Quote

Third option is set on
First and Section options are set on
First option is set on
Second option is set on


So, my question is:
Does C++ allow you to create enumerated variables (datatypes)? Or do you always have to use ints?

If it doesn't allow for enumerated variables (datatypes) what is the point of doing this:
enum Options{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};


instead of this:
enum{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};


?

They both give me the same output.

Thanks for your time.
Was This Post Helpful? 0
  • +
  • -

#4 sparkart  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 113
  • View blog
  • Posts: 688
  • Joined: 16-February 09

Posted 06 August 2009 - 12:04 PM

You're right.... unlike C, C++ requires an explicit conversion. Let me update the tutorial.

The point of naming the enum is to make things more obvious, which I believe is very important.

Edit:
Cannot seem to edit the first post.

This post has been edited by e_barroga: 06 August 2009 - 12:08 PM

Was This Post Helpful? 0
  • +
  • -

#5 PlasticineGuy  Icon User is offline

  • mov dword[esp+eax],0
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,436
  • Joined: 03-January 10

Posted 03 January 2010 - 04:00 AM

Thank you, I found this post very helpful.

I felt that I should inform users how to turn off switches. Using bitwise XOR (^) allows you to toggle options on and off, rather than just on. Bitwise OR is very useful for options for functions, but not so for options in games.
Was This Post Helpful? 0
  • +
  • -

#6 sparkart  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 113
  • View blog
  • Posts: 688
  • Joined: 16-February 09

Posted 02 July 2010 - 01:59 AM

View PostBetaWar, on 29 July 2009 - 01:58 PM, said:

So, my question is:
Does C++ allow you to create enumerated variables (datatypes)? Or do you always have to use ints?

If it doesn't allow for enumerated variables (datatypes) what is the point of doing this:
enum Options{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};


instead of this:
enum{
	none = 0,
	firstOption = 1,
	second = 2,
	third = 4,
	fourth = 8
};


?

They both give me the same output.

Thanks for your time.

This may seem like a late response, but I believe my previous reply did not answer your question.

C++ does allow you to create enumerated objects:
enum Options
{
    First = 0, Second, Third
};

Options object;
object = First;



The problem is that unlike C, C++ does not perform an implicit conversion between int and enum.
// Bitwise OR requires 'int' so a cast is necessary.
object = First | Second;


A quick fix to this solution is to overload the bitwise OR so that it performs the cast:
Options operator|( Options first, Options second )
{
    return (Options)( (int)first | (int)second );
}

Options o;
o = First | Second | Third; // Now, this is valid, because the cast is performed.


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1