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

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?

227745 次浏览

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

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

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

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.

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.

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

Using std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();