How to Toggle all bits in a number? [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 23 days ago.
Improve this question
#include <stdio.h>
int main() {
int n = 10;
int ans = n ^ (1 << 2);
printf("%d", ans);
}
this code toggle specific digits, But I need entire bits to toggle
example: 10 -> 0b1010 -> 0b0101 -> 5

You toggle all bits with tilde (~):
#include<stdio.h>
int main(void)
{
int n = 10;
int ans = ~n; // toggle all bits with "tilde"
printf("%08x %3d\n"
"%08x %3d\n", n, n, ans, ans);
}
Possible output:
0000000a 10
fffffff5 -11
There was a new requirement after I posted this answer:
But I need entire bits to toggle example: 10 -> 1010 -> 0101 -> 5
You could create some macros to help you to toggle the exact bits you're interested in. I've created a few below to get you started. They are probably not the most elegant bit twiddling macros around but should be clear enough for you to decipher.
#include <stdio.h>
#include <limits.h>
// the number of bits in the supplied `v`:
#define BITS(v) (sizeof(v) * CHAR_BIT)
// right-shift all but `n` bits from ~0ull (an unsigned long long with all 1:s)
// if `n == 0` we right-shift one less than wanted and remove it afterwards,
// creating a mask with all zeroes
#define MASKnBITS(n) ((~0ull >> (BITS(~0ull) - ((n) + ((n)==0)))) - ((n) == 0))
// create a mask for a range of bits. Example: 4,8 will create the mask
// ...11110000
#define MASKRANGE(bx,by) (MASKnBITS(by)^MASKnBITS(bx))
// toggle the bits in a masked range by using XOR:
#define TOGGLEBITSbxTOby(bx,by,v) (MASKRANGE((bx),(by)) ^ (v))
Usage:
int main(void) {
// some examples:
printf("%llx\n", MASKnBITS(4)); // f
printf("%llx\n", MASKnBITS(8)); // ff
printf("%llx\n", MASKRANGE(4,8)); // f0 == 0f ^ ff
printf("%llx\n", MASKRANGE(8,4)); // f0 == ff ^ 0f
// your case:
int n = 10;
int ans = TOGGLEBITSbxTOby(4,0,n); // toggle the 4 least significant bits
printf("%d\n", ans); // 5
}

As Ted and others have mentioned Bitwise Compliment Operator ~ can be used to flip all the bits in a number.
For your problem though, you can use the following:
#include <stdio.h>
int main() {
int n = -3;
int inv = 0;
int size = sizeof(n)*8;
int in[size],x;
if(n>=0){
for(int i=0; i<size;i++){
x = ((n >> (size - i -1)) & 1);
if(x)
inv = 1;
if(inv) {
in[i] = !x;
} else {
in[i] = x;
}
}
} else {
for(int i=0; i<size;i++){
x = ((n >> (size - i -1)) & 1);
if(!x)
inv = 1;
if(inv) {
in[i] = !x;
} else {
in[i] = x;
}
}
}
for(int i=0; i<size;i++){
printf("%d",in[i]);
}
}
basically looping over all the bits, storing them in an array and inverting them if the inv flag is high...which itself gets high when the first 1 or in case of negative numbers 0 is reached, leaving all the leading 0's or 1's intact.

Related

Why is the wrong binary number displayed?

Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
printf("%c", (x & 0x80) ? '1' : '0');
x <<= 1;
}
printf("\n");
return 0;
}
This code is supposed to convert a decimal int to binary, but why doesn't it work correctly?
P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?
EDIT2:
OP asks "P.S. I solved this problem by replacing 0x80 with 0x80000000. But why was the wrong number displayed at 0x80?"
What was wrong was 0x80 is equal to 0x00000080. 0x80 will never test any bits above b7 (where bits, right to left, are numbered b0 to b31.
The corrected value, 0x80000000, sets the MSB high and can be used (kind of) to 'sample' each bit of the data as the data value is 'scrolled' to the left.
//end edit2
Two concerns:
1) Mucking with the sign bit of a signed integer can be problematic
2) "Knowing" there are 32 bits can be problematic.
The following makes fewer presumptions. It creates a bit mask (only the MSB is set in an unsigned int value) and shifts that mask toward the LSB.
int main() {
long int x = 100000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 )
printf("%c", (x & bit) ? '1' : '0');
printf("\n");
return 0;
}
100000
00000000000000011000011010100000
Bonus: Here is a version of the print statement that doesn't involve branching:
printf( "%c", '0' + !!(x & bit) );
EDIT:
Having seen the answer by #Lundin, the suggestion to insert SP's to improve readability is an excellent idea! (Full credit to #Lundin.)
Below, not only is the long string of bits output divided into "hexadecimal" chunks, but the compile time value is shown in a way to easily see it is 10million. (1e7 would have done, too.)
A new-and-improved version:
#include <stdio.h>
#include <stdlib.h>
int main() {
long int x = 10 * 1000 *1000;
printf("%ld\n", x);
for( unsigned long int bit = ~(~0u >> 1); bit; bit >>= 1 ) {
putchar( '0' + !!(x & bit) );
if( bit & 0x11111111 ) putchar( ' ' );
}
putchar( '\n' );
return 0;
}
10000000
0000 0000 1001 1000 1001 0110 1000 0000
1000000 dec = 11110100001001000000 bin.
80 hex = 10000000 bin.
And this doesn't make much sense at all:
11110100001001000000
& 10000000
Instead fix the loop body to something like this:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
long int x;
x = 1000000;
printf("%ld\n", x);
for(int i = 0; i < 32; i++)
{
unsigned long mask = 1u << (31-i);
printf("%c", (x & mask) ? '1' : '0');
if((i+1) % 8 == 0) // to print a space after 8 digits
printf(" ");
}
printf("\n");
return 0;
}
Without using an integer counter to see what digit is at the ith position, you can instead use an unsigned variable which is equal to 2^i at the ith iteration. If this variable is unsigned, when it overflows it will become zero. Here is how the code would look like. It displays the number in reversed order (first position means the coefficient of 2^0 in the polynomial decomposition of the number).
int
main()
{
int x;
x = 1000000;
printf("%lx\n", x);
for(unsigned b = 1; b; b<<=1)
printf("%c", x & b ? '1':'0');
printf("\n");
return 0;
}
I would use functions
void printBin(long int x)
{
unsigned long mask = 1UL << (sizeof(mask) * CHAR_BIT - 1);
int digcount = 0;
while(mask)
{
printf("%d%s", !!(x & mask), ++digcount % 4 ? "" : " ");
mask >>= 1;
}
}
int main(void)
{
printBin(0); printf("\n");
printBin(1); printf("\n");
printBin(0xf0); printf("\n");
printBin(-10); printf("\n");
}

c, obtaining a special random number

I have a algorithm problem that I need to speed up :)
I need a 32bit random number, with exact 10 bits set to 1. But in the same time, patterns like 101 (5 dec) and 11 (3 dec) to be considered illegal.
Now the MCU is a 8051 (8 bit) and I tested all this in Keil uVision. My first attempt completes, giving the solution
0x48891249
1001000100010010001001001001001 // correct, 10 bits 1, no 101 or 11
The problem is that it completes in 97 Seconds or 1165570706 CPU cycles which is ridiculous!!!
Here is my code
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(unsigned long num)
{
unsigned char tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
unsigned long v,num; // count the number of bits set in v
unsigned long c; // c accumulates the total bits set in v
do {
num = (unsigned long)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
}while(c != 10 || checkFive(num));
while(1);
}
The big question for a brilliant mind :)
Can be done faster? Seems that my approach is naive.
Thank you in advance,
Wow, I'm impressed, thanks all for suggestions. However, before accept, I need to test them these days.
Now with the first option (look-up) it's just not realistic, will complete blow my 4K RAM of entire 8051 micro controller :) As you can see in image bellow, I tested for all combinations in Code Blocks but there are way more than 300 and it's not finished yet until 5000 index...
The code I use to test
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
//#define bool bit
//#define true 1
//#define false 0
// returns 1 if number is not good. ie. contains at leats one 101 bit sequence
bool checkFive(uint32_t num)
{
uint8_t tmp;
do {
tmp = (unsigned char)num;
if(
(tmp & 7) == 5
|| (tmp & 3) == 3
) // illegal pattern 11 or 101
return true; // found
num >>= 1;
}while(num);
return false;
}
void main(void) {
uint32_t v,num; // count the number of bits set in v
uint32_t c, count=0; // c accumulates the total bits set in v
//printf("Program started \n");
num = 0;
printf("Program started \n");
for(num=0; num <= 0xFFFFFFFF; num++)
{
//do {
//num = (uint32_t)rand() << 16 | rand();
v = num;
// count all 1 bits, Kernigen style
for (c = 0; v; c++)
v &= v - 1; // clear the least significant bit set
//}while(c != 10 || checkFive(num));
if(c != 10 || checkFive(num))
continue;
count++;
printf("%d: %04X\n", count, num);
}
printf("Complete \n");
while(1);
}
Perhaps I can re-formulate the problem:
I need a number with:
precise (known) amount of 1 bits, 10 in my example
not having 11 or 101 patterns
remaining zeroes can be any
So somehow, shuffle only the 1 bits inside.
Or, take a 0x00000000 and add just 10 of 1 bits in random positions, except the illegal patterns.
Solution
Given a routine r(n) that returns a random integer from 0 (inclusive) to n (exclusive) with uniform distribution, the values described in the question may be generated with a uniform distribution by calls to P(10, 4) where P is:
static uint32_t P(int a, int b)
{
if (a == 0 && b == 0)
return 0;
else
return r(a+b) < a ? P(a-1, b) << 3 | 1 : P(a, b-1) << 1;
}
The required random number generator can be:
static int r(int a)
{
int q;
do
q = rand() / ((RAND_MAX+1u)/a);
while (a <= q);
return q;
}
(The purpose of dividing by (RAND_MAX+1u)/a and the do-while loop is to trim the range of rand to an even multiple of a so that bias due to a non-multiple range is eliminated.)
(The recursion in P may be converted to iteration. This is omitted as it is unnecessary to illustrate the algorithm.)
Discussion
If the number cannot contain consecutive bits 11 or 101, then the closest together two 1 bits can be is three bits apart, as in 1001. Fitting ten 1 bits in 32 bits then requires at least 28 bits, as in 1001001001001001001001001001. Therefore, to satisfy the constraints that there is no 11 or 101 and there are exactly 10 1 bits, the value must be 1001001001001001001001001001 with four 0 bits inserted in some positions (including possibly the beginning or the end).
Selecting such a value is equivalent to placing 10 instances of 001 and 4 instances of 0 in some order.1 There are 14! ways of ordering 14 items, but any of the 10! ways of rearranging the 10 001 instances with each other are identical, and any of the 4! ways of rearranging the 0 instances with each other are identical, so the number of distinct selections is 14! / 10! / 4!, also known as the number of combinations of selecting 10 things from 14. This is 1,001.
To perform such a selection with uniform distribution, we can use a recursive algorithm:
Select the first choice with probability distribution equal to the proportion of the choices in the possible orderings.
Select the remaining choices recursively.
When ordering a instances of one object and b of a second object, a/(a+b) of the potential orderings will start with the first object, and b/(a+b) will start with the second object. Thus, the design of the P routine is:
If there are no objects to put in order, return the empty bit string.
Select a random integer in [0, a+b). If it is less than a (which has probability a/(a+b)), insert the bit string 001 and then recurse to select an order for a-1 instances of 001 and b instances of 0.
Otherwise, insert the bit string 0 and then recurse to select an order for a instances of 001 and b-1 instances of 0.
(Since, once a is zero, only 0 instances are generated, if (a == 0 && b == 0) in P may be changed to if (a == 0). I left it in the former form as that shows the general form of a solution in case other strings are involved.)
Bonus
Here is a program to list all values (although not in ascending order).
#include <stdint.h>
#include <stdio.h>
static void P(uint32_t x, int a, int b)
{
if (a == 0 && b == 0)
printf("0x%x\n", x);
else
{
if (0 < a) P(x << 3 | 1, a-1, b);
if (0 < b) P(x << 1, a, b-1);
}
}
int main(void)
{
P(0, 10, 4);
}
Footnote
1 This formulation means we end up with a string starting 001… rather than 1…, but the resulting value, interpreted as binary, is equivalent, even if there are instances of 0 inserted ahead of it. So the strings with 10 001 and 4 0 are in one-to-one correspondence with the strings with 4 0 inserted into 1001001001001001001001001001.
One way to satisfy your criteria in a limited number of solutions is to utilize the fact that there can be no more that four groups of 000s within the bit population. This also means that there can one be one group of 0000 in the value. Knowing this, you can seed your value with a single 1 in bits 27-31 and then continue adding random bits checking that each bit added satisfies your 3 or 5 constraints.
When adding random bits to your value and satisfying your constraints, there can always be combinations that lead to a solution that can never satisfy all constraints. To protect against those cases, just keep an iteration count and reset/restart the value generation if iterations exceed that value. Here, if a solution is going to be found, it will be found in less than 100 iterations. And is generally found in 1-8 attempts. Meaning for each value you generate, you have on average no more than 800 iterations which will be a far cry less than "97 Seconds or 1165570706 CPU cycles" (I haven't counted cycles, but the return is almost instantaneous)
There are many ways to approach this problem, this is just one that worked in a reasonable amount of time:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#define BPOP 10
#define NBITS 32
#define LIMIT 100
/** rand_int for use with shuffle */
static int rand_int (int n)
{
int limit = RAND_MAX - RAND_MAX % n, rnd;
rnd = rand();
for (; rnd >= limit; )
rnd = rand();
return rnd % n;
}
int main (void) {
int pop = 0;
unsigned v = 0, n = NBITS;
size_t its = 1;
srand (time (NULL));
/* one of first 5 bits must be set */
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
pop++; /* increment pop count */
while (pop < BPOP) { /* loop until pop count 10 */
if (++its >= LIMIT) { /* check iterations */
#ifdef DEBUG
fprintf (stderr, "failed solution.\n");
#endif
pop = its = 1; /* reset for next iteration */
v = 0;
v |= 1u << (NBITS - 1 - rand_int (sizeof v + 1));
}
unsigned shift = rand_int (NBITS); /* get random shift */
if (v & (1u << shift)) /* if bit already set */
continue;
/* protect against 5 (101) */
if ((shift + 2) < NBITS && v & (1u << (shift + 2)))
continue;
if ((int)(shift - 2) >= 0 && v & (1u << (shift - 2)))
continue;
/* protect against 3 (11) */
if ((shift + 1) < NBITS && v & (1u << (shift + 1)))
continue;
if ((int)(shift - 1) >= 0 && v & (1u << (shift - 1)))
continue;
v |= 1u << shift; /* add bit at shift */
pop++; /* increment pop count */
}
printf ("\nv : 0x%08x\n", v); /* output value */
while (n--) { /* output binary confirmation */
if (n+1 < NBITS && (n+1) % 4 == 0)
putchar ('-');
putchar ((v >> n & 1) ? '1' : '0');
}
putchar ('\n');
#ifdef DEBUG
printf ("\nits: %zu\n", its);
#endif
return 0;
}
(note: you will probably want a better random source like getrandom() or reading from /dev/urandom if you intend to generate multiple random solutions within a loop -- expecially if you are calling the executable in a loop from your shell)
I have also included a DEBUG define that you can enable by adding the -DDEBUG option to your compiler string to see the number of failed solutions and number of iterations on the final.
Example Use/Output
The results for 8 successive runs:
$ ./bin/randbits
v : 0x49124889
0100-1001-0001-0010-0100-1000-1000-1001
v : 0x49124492
0100-1001-0001-0010-0100-0100-1001-0010
v : 0x48492449
0100-1000-0100-1001-0010-0100-0100-1001
v : 0x91249092
1001-0001-0010-0100-1001-0000-1001-0010
v : 0x92488921
1001-0010-0100-1000-1000-1001-0010-0001
v : 0x89092489
1000-1001-0000-1001-0010-0100-1000-1001
v : 0x82491249
1000-0010-0100-1001-0001-0010-0100-1001
v : 0x92448922
1001-0010-0100-0100-1000-1001-0010-0010
As Eric mentioned in his answer, since each 1 but must be separated by at least two 0 bits, you basically start with the 28-bit pattern 1001001001001001001001001001. It's then a matter of placing the remaining four 0 bits within this bit pattern, and there are 11 distinct places to insert each zero.
This can be accomplished by first selecting a random number from 1 to 11 to determine where to place a bit. Then you left shift all the bits above the target bit by 1. Repeat 3 more times, and you have your value.
This can be done as follows:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
void binprint(uint32_t n)
{
int i;
for (i=0;i<32;i++) {
if ( n & (1u << (31 - i))) {
putchar('1');
} else {
putchar('0');
}
}
}
// inserts a 0 bit into val after pos "1" bits are found
uint32_t insert(uint32_t val, int pos)
{
int cnt = 0;
uint32_t mask = 1u << 31;
uint32_t upper, lower;
while (cnt < pos) {
if (val & mask) { // look for a set bit and count if you find one
cnt++;
}
mask >>= 1;
}
if (mask == (1u << 31)) {
return val; // insert at the start: no change
} else if (mask == 0) {
return val << 1; // insert at the end: shift the whole thing by 1
} else {
mask = (mask << 1) - 1; // mask has all bits below the target set
lower = val & mask; // extract the lower portion
upper = val & (~mask); // extract the upper portion
return (upper << 1) | lower; // recombine with the upper portion shifted 1 bit
}
}
int main()
{
int i;
uint32_t val = 01111111111; // hey look, a good use of octal!
srand(time(NULL));
for (i=0;i<4;i++) {
int p = rand() % 11;
printf("p=%d\n", p);
val = insert(val, p);
}
binprint(val);
printf("\n");
return 0;
}
Sample output for two runs:
p=3
p=10
p=9
p=0
01001001000100100100100100100010
...
p=3
p=9
p=3
p=1
10001001000010010010010010010001
Run time is negligible.
Since you don't want a lookup table here is the way:
Basically you have this number with 28 bits set to 0 and 1 in which you need to insert 4x 0 :
0b1001001001001001001001001001
Hence you can use the following algorithm:
int special_rng_nolookup(void)
{
int secret = 0b1001001001001001001001001001;
int low_secret;
int high_secret;
unsigned int i = 28; // len of secret
unsigned int rng;
int mask = 0xffff // equivalent to all bits set in integer
while (i < 32)
{
rng = __asm__ volatile(. // Pseudo code
"rdrand"
);
rng %= (i + 1); // will generate a number between 0 and 28 where you will add a 0. Then between 0 and 29, 30, 31 for the 3 next loop.
low_secret = secret & (mask >> (i - rng)); // locate where you will add your 0 and save the lower part of your number.
high_secret = (secret ^ low_secret) << (!(!rng)); // remove the lower part to your int and shift to insert a 0 between the higher part and the lower part. edit : if rng was 0 you want to add it at the very beginning (left part) so no shift.
secret = high_secret | low_secret; // put them together.
++i;
}
return secret;
}

Method for displaying binary number [C] [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Not sure why, but the number being outputted is:
101101
Instead of
1011010
Any ideas why?
Here's my code:
typedef unsigned short bitSet;
int main() {
bitSet bits = makeBitSet();
displayBitSet(bits);
}
bitSet makeBitSet() {
bitSet bits = 90;
return bits;
}
displayBitSet(bitSet bs) {
int i;
for (i = 0; i < 16; i++) {
printf("%d", ((bs & (int)pow(2, (16-1))) >> (16-i)));
}
}
void displayBitSet(bitSet bs) {
for(int i = 15; i >= 0; --i)
printf("%d", (bs >> i) & 1);
}
I'm not sure why you're using a floating point pow function for this. Maybe I misunderstand the question?
90=64+0+16+8+0+0+2+0
1 0 1 1 0 0 1 0
The answer you are expecting is 9 binary,followed by 10 binary.
If you were trying to display 16 bits, using pow is not necessary like #Clark Gaebel said. If you are looking for a reference, have a look at below link.
The link contains both using printf and string/char*
http://www.programmingsimplified.com/c/source-code/c-program-convert-decimal-to-binary
I have a clumsy but visualized method to solve "Method for displaying binary number" for a number of 16 bits. And 32 bits is alike.
#include<stdio.h>
#include<string.h>
typedef struct {
unsigned short b0 : 1, b1 : 1, b2 : 1, b3 : 1, b4 : 1, b5 : 1, b6 : 1, b7 : 1, b8 : 1, b9 : 1, b10 : 1, b11 : 1, b12 : 1, b13 : 1, b14 : 1, b15 : 1;
}stBit;
_Bool isBigEndian() {
union {
unsigned short a;
unsigned char b[2];
}n;
n.a = 0xFF00;
return n.b[0] == 0xFF;
}
void printStBit(stBit s) {
if (isBigEndian()) {
printf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d\n", s.b0, s.b1, s.b2, s.b3, s.b4, s.b5, s.b6, s.b7, s.b8, s.b9, s.b10, s.b11, s.b12, s.b13, s.b14, s.b15);
}
else {
printf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d\n", s.b8, s.b9, s.b10, s.b11, s.b12, s.b13, s.b14, s.b15, s.b0, s.b1, s.b2, s.b3, s.b4, s.b5, s.b6, s.b7);
}
}
int main(void) {
unsigned short n = 90;
stBit s;
memcpy(&s, &n, sizeof n);
printStBit(s);
getchar();
return 0;
}
the result is
Resursion is useful to print binary digits while suppressing leading zero.
#include <stdio.h>
#include <math.h>
typedef unsigned short bitSet;
bitSet makeBitSet(void);
void displayBitSet(bitSet bs) ;
int main(void) {
bitSet bits = makeBitSet();
displayBitSet(bits);
return 0;
}
bitSet makeBitSet(void) {
bitSet bits = 90;
return bits;
}
void displayBitSet(bitSet bs) {
bitSet bsNext = bs >> 1;
if (bsNext) displayBitSet(bsNext);
printf("%d", bs & 1);
}
To specify the minimum number of digit to print, you can do so like this:
void displayBitSet2(bitSet bs, int minDigit) {
bitSet bsNext = bs >> 1;
int minDigitNext = (minDigit > 0 ? minDigit - 1 : 0);
if (bsNext || minDigit > 1) displayBitSet2(bsNext, minDigitNext);
printf("%d", bs & 1);
}
example: displayBitSet2(0x90, 16); to print at least 16 digits.

How to get certain bits of a char array to another char array in C?

I have a char (input) array with size 60. I want to write a function that returns certain bits of the input array.
char input_ar[60];
char output_ar[60];
void func(int bits_starting_number, int total_number_bits){
}
int main()
{
input_ar[0]=0b11110001;
input_ar[1]=0b00110011;
func(3,11);
//want output_ar[0]=0b11000100; //least significant 6 bits of input_ar[0] and most significant bits (7.8.) of input_ar[1]
//want output_ar[1]=0b00000110; //6.5.4. bits of input_ar[1] corresponds to 3 2 1. bits of output_ar[1] (110) right-aligned other bits are 0, namely 8 7 ...4 bits is zero
}
I want to ask what's the termiology of this algorithm? How can I easily write the code? Any clues appricated.
Note: I use XC8, arrray of bits are not allowed.
This answer makes the following assumptions. Bits are numbered from 1, the first bit is the MS bit of the first byte. The extracted bit array must be left-aligned. Unused bits on the right are padded with 0.
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX_LEN 60
#define BMASK (1 << (CHAR_BIT-1))
unsigned char input_ar[MAX_LEN];
unsigned char output_ar[MAX_LEN];
int func(int bits_starting_number, int total_number_bits) {
// return the number of bits copied
int sors_ind, sors_bit, dest_ind = 0;
int i, imask, omask;
memset (output_ar, 0, MAX_LEN); // clear the result
if (bits_starting_number < 1 || bits_starting_number > MAX_LEN * CHAR_BIT)
return 0; // bit number is out of range
if (total_number_bits < 1)
return 0; // nothing to do
bits_starting_number--;
if (bits_starting_number + total_number_bits > MAX_LEN * CHAR_BIT)
total_number_bits = MAX_LEN * CHAR_BIT - bits_starting_number;
sors_ind = bits_starting_number / CHAR_BIT;
sors_bit = CHAR_BIT - 1 - (bits_starting_number % CHAR_BIT);
imask = 1 << sors_bit;
omask = BMASK;
for (i=0; i<total_number_bits; i++) {
if (input_ar[sors_ind] & imask)
output_ar[dest_ind] |= omask; // copy a 1 bit
if ((imask >>= 1) == 0) { // shift the input mask
imask = BMASK;
sors_ind++; // next input byte
}
if ((omask >>= 1) == 0) { // shift the output mask
omask = BMASK;
dest_ind++; // next output byte
}
}
return total_number_bits;
}
void printb (int value) {
int i;
for (i=BMASK; i; i>>=1) {
if (value & i)
printf("1");
else
printf("0");
}
printf (" ");
}
int main(void) {
int i;
input_ar[0]= 0xF1; // 0b11110001
input_ar[1]= 0x33; // 0b00110011
printf ("Input: ");
for (i=0; i<4; i++)
printb(input_ar[i]);
printf ("\n");
func(3,11);
printf ("Output: ");
for (i=0; i<4; i++)
printb(output_ar[i]);
printf ("\n");
return 0;
}
Program output
Input: 11110001 00110011 00000000 00000000
Output: 11000100 11000000 00000000 00000000
First of all, the returntype: You can return a boolean array of length total_number_bits.
Inside your function you can do a forloop, starting at bits_starting_number, iterating total_number_bits times. For each number you can divide the forloopindex by 8 (to get the right char) and than bitshift a 1 by the forloopindex modulo 8 to get the right bit. Put it on the right spot in the output array (forloopindex - bits_starting_number) and you are good to go
This would become something like:
for(i = bits_starting_number; i < bits_starting_number + total_number_bits; i++) {
boolarr[i - bits_starting_number] = charray[i/8] & (1 << (i % 8));
}

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?
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");
}
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.
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;
}
Using std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
#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;
}
#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.

Resources