130

I want to extract bits of a decimal number.

For example, 7 is binary 0111, and I want to get 0 1 1 1 all bits stored in bool. How can I do so?

OK, a loop is not a good option, can I do something else for this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Badr
  • 10,384
  • 15
  • 70
  • 104

8 Answers8

199

If you want the k-th bit of n, then do

(n & ( 1 << k )) >> k

Here we create a mask, apply the mask to n, and then right shift the masked value to get just the bit we want. We could write it out more fully as:

    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;

You can read more about bit-masking here.

Here is a program:

#include <stdio.h>
#include <stdlib.h>

int *get_bits(int n, int bitswanted){
  int *bits = malloc(sizeof(int) * bitswanted);

  int k;
  for(k=0; k<bitswanted; k++){
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

int main(){
  int n=7;

  int  bitswanted = 5;

  int *bits = get_bits(n, bitswanted);

  printf("%d = ", n);

  int i;
  for(i=bitswanted-1; i>=0;i--){
    printf("%d ", bits[i]);
  }

  printf("\n");
}
Box Box Box Box
  • 5,094
  • 10
  • 49
  • 67
forefinger
  • 3,767
  • 1
  • 22
  • 18
  • 83
    `(n >> k) & 1` is equally valid and does not require computing the mask as the mask is constant due to shifting before masking instead of the other way around. – Joe May 22 '13 at 15:37
  • @Joe can you explain that, perhaps in an answer, please? – Dan Rosenstark Oct 06 '14 at 23:43
  • 1
    @Yar extended my comment a little and added a new answer as requested – Joe Oct 07 '14 at 07:17
  • When using known bits for information (i.e. for network protocols, such as Websockets), casting the data onto a `struct` can be useful too, as you get all the required data with a single operation. – Myst Dec 29 '15 at 06:34
  • @forefinger, can you please post an example output of the code. – Box Box Box Box Jan 09 '16 at 03:36
  • Why dont you type bit values by the lines for better understanding? – TomeeNS Aug 01 '17 at 00:15
105

As requested, I decided to extend my comment on forefinger's answer to a full-fledged answer. Although his answer is correct, it is needlessly complex. Furthermore all current answers use signed ints to represent the values. This is dangerous, as right-shifting of negative values is implementation-defined (i.e. not portable) and left-shifting can lead to undefined behavior (see this question).

By right-shifting the desired bit into the least significant bit position, masking can be done with 1. No need to compute a new mask value for each bit.

(n >> k) & 1

As a complete program, computing (and subsequently printing) an array of single bit values:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    unsigned
        input = 0b0111u,
        n_bits = 4u,
        *bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
        bit = 0;

    for(bit = 0; bit < n_bits; ++bit)
        bits[bit] = (input >> bit) & 1;

    for(bit = n_bits; bit--;)
        printf("%u", bits[bit]);
    printf("\n");

    free(bits);
}

Assuming that you want to calculate all bits as in this case, and not a specific one, the loop can be further changed to

for(bit = 0; bit < n_bits; ++bit, input >>= 1)
    bits[bit] = input & 1;

This modifies input in place and thereby allows the use of a constant width, single-bit shift, which may be more efficient on some architectures.

Community
  • 1
  • 1
Joe
  • 6,497
  • 4
  • 29
  • 55
14

Here's one way to do it—there are many others:

bool b[4];
int v = 7;  // number to dissect

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));

It is hard to understand why use of a loop is not desired, but it is easy enough to unroll the loop:

bool b[4];
int v = 7;  // number to dissect

b [0] =  0 != (v & (1 << 0));
b [1] =  0 != (v & (1 << 1));
b [2] =  0 != (v & (1 << 2));
b [3] =  0 != (v & (1 << 3));

Or evaluating constant expressions in the last four statements:

b [0] =  0 != (v & 1);
b [1] =  0 != (v & 2);
b [2] =  0 != (v & 4);
b [3] =  0 != (v & 8);
wallyk
  • 56,922
  • 16
  • 83
  • 148
3

Here's a very simple way to do it;

int main()
{
    int s=7,l=1;
    vector <bool> v;
    v.clear();
    while (l <= 4)
    {
        v.push_back(s%2);
        s /= 2;
        l++;
    }
    for (l=(v.size()-1); l >= 0; l--)
    {
        cout<<v[l]<<" ";
    }
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
d3vdpro
  • 2,887
  • 4
  • 25
  • 29
2

Using std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
Smit Ycyken
  • 1,189
  • 1
  • 11
  • 25
  • 6
    It's a useful method, but there's something wrong in the example. bitset, n is the number of bit, so the usage of sizeof(int) is wrong. – Jerry Chou Apr 15 '19 at 06:09
  • 1
    thanks for exposing me to bitset is helped me find solutions using it. But as @JerryChou mentioned using sizeof(int) seems wrong as it returns the number of bytes (4) and not the number of bits (32). Also in the question he asked to take specific bits and not converting the whole int num to bits. So I suggest the following code: ''' int value = 123; int bitswanted = 5; std::bitset bits(value); std::cout < – Or Hirshfeld Oct 20 '22 at 11:45
1

@prateek thank you for your help. I rewrote the function with comments for use in a program. Increase 8 for more bits (up to 32 for an integer).

std::vector <bool> bits_from_int (int integer)    // discern which bits of PLC codes are true
{
    std::vector <bool> bool_bits;

    // continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
    for (int i = 0; i < 8; i++)
    {
        bool_bits.push_back (integer%2);    // remainder of dividing by 2
        integer /= 2;    // integer equals itself divided by 2
    }

    return bool_bits;
}
xinthose
  • 3,213
  • 3
  • 40
  • 59
0
#include <stdio.h>

int main(void)
{
    int number = 7; /* signed */
    int vbool[8 * sizeof(int)];
    int i;
        for (i = 0; i < 8 * sizeof(int); i++)
        {
            vbool[i] = number<<i < 0;   
            printf("%d", vbool[i]);
        }
    return 0;
}
anon
  • 1
  • 3
0

If you don't want any loops, you'll have to write it out:

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

int main(void)
{
    int num = 7;

    #if 0
        bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
    #else
        #define BTB(v,i) ((v) & (1u << (i))) ? true : false
        bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
        #undef BTB
    #endif

    printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);

    return 0;
}

As demonstrated here, this also works in an initializer.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wildplasser
  • 43,142
  • 8
  • 66
  • 109