how can I create a bitmaped data in c?

Viewed 101

I am trying to create a bitmaped data in , here is the code I used but I am not able to figure the right logic. Here's my code

bool a=1;
bool b=0;
bool c=1;
bool d=0;

uint8_t output = a|b|c|d;

printf("outupt = %X", output);

I want my output to be "1010" which is equivalent to hex "0x0A". How do I do it ??

3 Answers

The bitwise or operator ors the bits in each position. The result of a|b|c|d will be 1 because you're bitwise oring 0 and 1 in the least significant position.

You can shift (<<) the bits to the correct positions like this:

uint8_t output = a << 3 | b << 2 | c << 1 | d;

This will result in

    00001000 (a << 3)
    00000000 (b << 2)
    00000010 (c << 1)
  | 00000000 (d; d << 0)
    --------
    00001010 (output)

Strictly speaking, the calculation happens with ints and the intermediate results have more leading zeroes, but in this case we do not need to care about that.

If you're interested in setting/clearing/accessing very simply specific bits, you could consider std::bitset:

bitset<8> s;   // bit set of 8 bits

s[3]=a;        // access individual bits, as if it was an array
s[2]=b;
s[1]=c; 
s[0]=d;        // the first bit is the least significant bit

cout << s <<endl;       // streams the bitset as a string of '0' and '1' 
cout << "0x"<< hex << s.to_ulong()<<endl;    // convert the bitset to unsigned long
cout << s[3] <<endl;     // access a specific bit
cout << "Number of bits set: " << s.count()<<endl; 

Online demo

The advantage is that the code is easier to read and maintain, especially if you're modifying bitmapped data. Because setting specific bits using binary arithmetics with a combination of << and | operators as explained by Anttii is a vorkable solution. But clearing specific bits in an existing bitmap, by combining the use of << and ~ (to create a bit mask) with & is a little more tricky.

Another advantage is that you can easily manage large bitsets of hundreds of bits, much larger than the largest built-in type unsigned long long (although doing so will not allow you to convert as easily to an unsigned long or an unsigned long long: you'll have to go via a string).

C only

I would use bitfields. I know that they are not portable, but for the particular embedded hardware (especially uCs) it is well defined.

#include <string.h>
#include <stdio.h>
#include <stdbool.h>


typedef union 
{
    struct 
    {
        bool a:1;
        bool b:1;
        bool c:1;
        bool d:1;
        bool e:1;
        bool f:1;
    };
    unsigned char byte;
}mydata;


int main(void)
{
    mydata d;

    d.a=1;
    d.b=0;
    d.c=1;
    d.d=0;

printf("outupt = %hhX", d.byte);
}
Related