Shifting bits in C

Shifting bits in C

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;
}

要查看或添加评论,请登录

Gabriel M.的更多文章

  • Docker 101

    Docker 101

    A (tiny) introduction to Docker. If you want to get your hands dirty with some Docker content, this quick introduction…

  • Building custom kernels for Linux + updating the system firmware.

    Building custom kernels for Linux + updating the system firmware.

    In this post I'll show you how you can replace your current Linux kernel with a new one built entirely from the…

  • Debian complained about missing firmware during installation? Add missing 'non-free' firmware to installation image! :)

    Debian complained about missing firmware during installation? Add missing 'non-free' firmware to installation image! :)

    If you have installed Debian, you might have faced the screen below: And probably got very frustrated, because your…

  • Using Traps in Bash Scripts

    Using Traps in Bash Scripts

    Imagine that you have a script to perform some critical operation, one that would render the system completely unusable…

    2 条评论
  • Safer Bash Scripting Tips

    Safer Bash Scripting Tips

    I hope you are all well and safe. As "stay safe" is the most used expression during this COVID-19 period, I thought it…

    1 条评论
  • Pointers and 2D-arrays in C

    Pointers and 2D-arrays in C

    When taking the Engineering or CS undergrad path, like 1+1 leads to 2 (let's keep it simple here, shall we?), students…

    2 条评论
  • Linux Kernel Inotify Subsystem

    Linux Kernel Inotify Subsystem

    When dealing with Unix-style filesystems there must be a data structure that is capable of describing an object from…

  • Linux File I/O

    Linux File I/O

    When using system calls for dealing with file I/O, open(), read(), write() and close() are the four functions used to…

  • Improving your Linux box security

    Improving your Linux box security

    Did you know that more than never, during these quarantine days, there is a lot more malicious activities undergoing…

  • Build UnrealEngine on Linux, making it use less disk space! :)

    Build UnrealEngine on Linux, making it use less disk space! :)

    If you are playing with the amazing Unreal Engine on your Linux box, you might have noticed that the final size after…

社区洞察

其他会员也浏览了