How do I get bit-by-bit data from an integer value in C?
Asked Answered
I

9

133

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?

Inky answered 12/2, 2010 at 4:51 Comment(0)
H
206

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");
}
Huguenot answered 12/2, 2010 at 4:54 Comment(6)
(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.Gloam
@Gloam can you explain that, perhaps in an answer, please?Cumulus
@Yar extended my comment a little and added a new answer as requestedGloam
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.Forsyth
@forefinger, can you please post an example output of the code.Licha
Why dont you type bit values by the lines for better understanding?Eldred
G
108

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.

Gloam answered 7/10, 2014 at 7:16 Comment(0)
T
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);
Twofold answered 12/2, 2010 at 4:55 Comment(0)
G
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;
}
Gatewood answered 12/2, 2010 at 5:2 Comment(0)
A
2

Using std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
Angeloangelology answered 12/5, 2017 at 14:47 Comment(2)
It's a useful method, but there's something wrong in the example. bitset<n>, n is the number of bit, so the usage of sizeof(int) is wrong.Grillage
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<bitswanted> bits(value); std::cout <<bits.to_string(); '''Paleobotany
D
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;
}
Deconsecrate answered 24/2, 2015 at 18:52 Comment(0)
R
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;
}
Rozek answered 20/5, 2013 at 2:55 Comment(0)
S
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.

Speak answered 20/5, 2013 at 11:17 Comment(0)
M
0

If I could rephrase the question, a more general request to extract a set of bits from an integer could be stated as:

I want to extract "size" number of bits from a decimal number "n" from "pos" bit onwards so that I get the bits starting from bit positions "pos + size" to "pos"

The more general statement above can then be stated as:

I want to extract 1 bit from a decimal number "n' from bit position "pos"

You can then change the above statement to:

I want to extract the bits of a from a decimal number "n" one bit at a time and store it into a boolean array so that the bit position "pos" corresponds to the array index "pos".

Assuming that the first "position" of the bit in the decimal number is the LSB i.e bit 0, we can extract n bits from a decimal number like this:

create mask for number of bits : (1 << size) - 1
shift the number by number of bits so that the bit at index is now the LSB : n >> pos
Logical AND the shifted value with the mask : (n >> pos) & ((1 << size) - 1)

Here is an example:

#define GET_N_BITS(n, size, pos, ret) ({ \
        ret = (n >> pos) & ((1 << size) - 1); \
)}

main()
{
        int n = 7;
        int extracted_bits = 0;
        // extract 2 bits from bit 1 onwards from decimal number 7
        GET_N_BITS(n, 2, 1, extracted_bits);
        // extracted bits = b0011 = 3
}

We can then change the above to extract and return one bit from a given bit position and store it in an array.

#define GET_NTH_BIT(n, pos) ({ \
        bool ret; \
        ret = (n >> pos) & 1 \
        ret; \
})

main()
{
        int n = 7, i = 0;
        bool n_bit_by_bit[32];
        for (i = 0 ; i < 32 ; i++)
                n_bit_by_bit[i] = GET_NTH_BIT(n, i);
}
Menado answered 21/3 at 8:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.