Shifting bits in C
Gabriel M.
Linux Systems Engineer | IT Infrastructure | Security | Virtualization | Automation | AI | C and Shell Scripting
Have you ever asked yourself how much memory space do you waste when writing your code? Sometimes you just need a single bit, but end up allocating a whole byte!
Here is a quick example in which I demonstrate how to use a single "char" (1 byte: 8 bits) for controlling 8 different actions for a fictional "super-advanced robot" ;). This can be very handy when you have limited space, when you are writing device drivers, or when working with embedded systems, where every optimization is more than welcome. Not only would you gain precious space, but also speed performance, depending on what you are trying to achieve.
So, let's got right to the code. The idea is simple: you have a fictional robot unit and want to enable (on/off) some of its functionalities. To achieve this, you can use a single 8 bits char variable (1 byte) and shift through its bit, making them as ON (1) or OFF (0), as seen in the example. For the sake of simplicity, we're just playing with ON/OFF. In a real-world example, do not forget to test the current state of the bit you want to change, before touching it ;)
/* * Flag bits test. * This program shows how to implement * flags operations using the eight bits * of a char variable. * * Gabriel Marques * [email protected] * 09.2012 * */ /* * Imagine you need to use flags to control * the state of something. Think of 8 flags, * for instance, for controlling 8 basic * functions of a super advanced robot! ;-) * * Things that require binary state, such as * Unit_Status, Engage_Battle, Force_Field, etc * require just an ON / OFF control. * * You could use variables to control each state, * but think of the huge waste you would have * as all of these states are binary values! * * char Unity_Status[] = "On"; <-- This would require * much more space than a simple 0 or 1 as it would * allocate memory for all the chars! * And you would also need to deal with strings * comparison to test each status! * * Even if you use a boolean, you're still allocating * 1 byte (8 bits), when you just need 1 bit! * * Now, think of a single bit for each status. * As a char variable is 1 byte long, we would * have 8 bits to store information on a single char! :-) * * Using bit shifts we could manipulate each bit inside * our 1 byte (8 bits) char! So, in this case you have * 8 storage places in one single variable! =) * * You can see the operation and the bit it affects below: * * Operation | Move 1st bit by | Result * ----------------------------------------------- * 1<<0 00000001 << 0 00000001 [Bit 0] * 1<<1 00000001 << 1 00000010 [Bit 1] * 1<<2 00000001 << 2 00000100 [Bit 2] * 1<<3 00000001 << 3 00001000 [Bit 3] * 1<<4 00000001 << 4 00010000 [Bit 4] * 1<<5 00000001 << 5 00100000 [Bit 5] * 1<<6 00000001 << 6 01000000 [Bit 6] * 1<<7 00000001 << 7 10000000 [Bit 7] * * Let's take a look at a simple example, regarding our * super advanced robot and its behavior ;-). * */ #include <stdio.h> #include <stdlib.h> /* Definition of each funcionality flag */ const unsigned char UNITY_STATUS = (1<<0); /* Bit 0 */ const unsigned char UNITY_ENGAGED_FOR_BATTLE = (1<<1); /* Bit 1 */ const unsigned char UNITY_DEFLECTOR_SHIELD = (1<<2); /* Bit 2 */ const unsigned char UNITY_LASER_CANNON = (1<<3); /* Bit 3 */ const unsigned char UNITY_MISSLE_ARMED = (1<<4); /* Bit 4 */ const unsigned char UNIT_DIAGNOSTIC_MODE = (1<<5); /* Bit 5 */ const unsigned char UNITY_AI_SYSTEM_FAILURE = (1<<6); /* Bit 6 */ const unsigned char UNITY_GENERAL_FAILURE = (1<<7); /* Bit 7 */ /* * Now that we have the flags defined we can manipulate * them to test if our robot (UNITY) has some modes ON or OFF * as you will see later inside the main program. */ int main() { unsigned char unity_control_flags; /* This controls our robot ;-) */ unity_control_flags = 0; /* This disables everything */ /* Let's turn our robot ON */ unity_control_flags |= UNITY_STATUS; /* Let's make our unity start its deflector shield */ unity_control_flags |= UNITY_DEFLECTOR_SHIELD; /* During a battle, let's suppose the system has been damaged */ unity_control_flags |= UNITY_GENERAL_FAILURE; /* * Now, let's test some status flags of our robot * We do this by testing if some bits are set to 1 * what will result in a TRUE test. */ /* Let's see if it is turned on*/ if ( (unity_control_flags & UNITY_STATUS) != 0 ) printf("Unity is on and waiting for instructions!\n"); else printf("Unity is off!\n"); /* Let's test if the unity has its shield on */ if ((unity_control_flags & UNITY_DEFLECTOR_SHIELD) != 0) printf("Unity has its deflector shield on!\n"); else printf("Deflector shield is down! Unity is vulnerable!\n"); /* And we do the same test for a general system failure */ if ((unity_control_flags & UNITY_GENERAL_FAILURE) != 0) printf("Warning! General system failure!\n"); else printf("Unity system is healthy!\n"); /* * Now let's suppose we need to turn some features off * Let's pretend we've just fixed your system failure problem. * We need to reset the corresponding flag! * * We do this by using the flags variable AND NOT the * desired functionality (~). This will turn that bit to * the opposite state. */ unity_control_flags &= ~UNITY_GENERAL_FAILURE; /* Let's check if it worked */ /* And we do the same test for a general system failure */ if ((unity_control_flags & UNITY_GENERAL_FAILURE) != 0) printf("Warning! General system failure!\n"); else printf("Unity system is healthy!\n"); return 0; }