Obtaining a sequence of bits from a C-style string in C? - c

I need to obtain a sequence of bits from a char* fixed length C-style string in C, how can I do it? I need a sequence of bits representing the string, not a particular one. I need to do it strictly in C not in C++.

You can use a simple bitmask of only one 1 and scan through the string one byte at a time, starting with mask = 0x80 (binary 10000000) and going down to 1 (binary 00000001).
#include <stdio.h>
#define N 5
int main(void) {
char mystring[N] = "abcd";
unsigned i;
unsigned char mask;
for (i = 0; i < N; i++) {
unsigned char c = mystring[i];
unsigned char mask = 0x80;
do {
putchar(c & mask ? '1' : '0');
mask >>= 1;
} while (mask > 0);
putchar(' ');
}
putchar('\n');
return 0;
}
Result:
01100001 01100010 01100011 01100100 00000000

Related

Two's Complement Representation of int16_t

I am attempting to display a string representation of an int16_t's Two's Complement. I find the two's complement by (uint16_t)~value + 1;
How would I add the 16 bits to a string?
char* getBits(const int16_t value) {
uint16_t complement = (uint16_t)~value + 1;
char bits = malloc(16*sizeof(char*))
for (int i = 0; i < 16; i++) {
bits[i] = // something
}
return bits;
}
Shift complement right i bits, and test whether the low-order bit is 0 or 1 and put the corresponding character in bits.
bits[i] = (complement >> i) & 1 ? '1' : '0';
Also, you need to allocate an extra character in your string for the null terminator. And bits needs to be a pointer, while the element size is sizeof(char), not sizeof(char*).
char *bits = malloc(17*sizeof(char));
bits[16] = 0;
There's no need to use the formula (uint16_t)~value + 1. Converting a signed int to unsigned int automatically returns its twos complement value. So you can simply do:
uint16_t complement = (uint16_t)value;
Your code has many issues and it wont even compile. You need to learn what is pointer and what is not. How to use malloc and where to sstore its result. The best way is to read a good C book.
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
char* getBits(const int16_t value)
{
uint16_t complement = value;
char *bits = malloc(sizeof(value) * CHAR_BIT + 1);
char *wrk = bits;
if(bits)
{
for (unsigned i = 1 << 15; i; i >>= 1)
{
*wrk++ = (complement & i) ? '1' : '0';
}
*wrk++ = 0;
}
return bits;
}
int main(void)
{
for(int i = 0; i > -15; i --)
{
char *bits;
printf("%d - %s\n", i, (bits = getBits(i)));
free(bits);
}
}

How to convert a char into an unsigned int?

How the program works
./my program 1 10000100 01000000001000001000000
// Reads the argv's
// Converts them into unsigned ints
How do I convert the char* into an unsigned int? I assume I use bit manipulation, but I am a little lost on the conversion of a char to an unsigned int.
The code.
struct _float {
unsigned int sign:1, exp:8, frac:23;
};
union _bits32 {
float fval; // Bits as a float
Word xval; // Bits as a word
Float32 bits; // manipulate individual bits
};
union _bits32 getBits(char *sign, char *exp, char *frac);
int main(int argc, char **argv) {
u = getBits(argv[1], argv[2], argv[3]);
return 0;
}
// Here I am converting the char's into unsigned ints
union _bits32 getBits(char *sign, char *exp, char *frac) {
Union32 new;
// convert char *sign into a single bit in new.bits
new.bits.sign = *sign;
// convert char *exp into an 8-bit value in new.bits
new.bits.exp = *exp;
// convert char *frac into a 23-bit value in new.bits
new.bits.frac = *frac;
return new;
}
So, you need to read each bit (1 character per bit) and save that to an integer in the correct bit positions. Here is a function that would do so for an arbitrary length up to 32 bits.
// Takes in the string with the bits (e.g. "01010100011")
// Returns the integer represented by those bits (leading bits are 0's)
int parseFromBinary(char* bitString) {
int val = 0;
int i = 0;
// While there are more characters
while (bitString[i] != 0) {
// Shift everything left (multiply by 2) to make room for the new bit
val <<= 1;
// Add the new bit (no effect if it is a 0)
val |= bitString[i] - '0';
i++;
}
return val;
}
You would want to call this function once for each field, though it really isn't necessary to loop over the 1 sign bit, and that would arguably make things less clear.
#include <stdio.h>
int main ( int argc, char *argv[])
{
unsigned int ra,rb;
if(argc<2) return(1);
rb=0;
for(ra=0;argv[1][ra];ra++)
{
rb<<=1;
rb|=argv[1][ra]&1;
}
printf("0x%08X\n",rb);
return(0);
}
build and run
gcc so.c -o so
./so 000100000
0x00000020
./so 101010101
0x00000155
./so 010101010
0x000000AA
./so 101
0x00000005
the string "101" looks like this when run:
argv[1]={0x31,0x30,0x31};
because it is ASCII. (google ASCII chart and go to images)
The desired result is the value 0b101 which is 0x5 or decimal 5.
Generally you want to parse through that string
argv[1][0]=0x31;
argv[1][1]=0x30;
argv[1][2]=0x31;
argv[1][3]=0x00;
starting with the first byte in the string 0x31 need to extract the lsbit and save it. This is the 0b1xx bit of our final number which we can see as humans but need to get the program to do it. When on to the next byte if you shift your accumulator left one and make room for the next bit you will end up with 0b10 and orr in a zero ending up with 0b10 which is these two bits of our final answer 0b10x
now shift the 0b10 left one to make room for the next bit, take that bit from the ascii byte resulting in 0b101. You can repeat this as long as you have room in the variable.
Because the string order left to right is array item 0,1,2,3. And these line up with the msbit to lsbit in that order of the binary value we want to extract the first byte in the array is our msbit, so if we keep shifting that left as we add in more bits our msbit ends up on the left as desired and the last bit we add, the last byte in the string, and that will be the lsbit when done.
EDIT
#include <stdio.h>
int main ( int argc, char *argv[])
{
unsigned int ra,rb;
if(argc<2) return(1);
rb=0;
for(ra=0;argv[1][ra];ra++)
{
rb<<=1;
rb|=argv[1][ra]&1;
}
//printf("0x%08X\n",rb);
printf("0b");
for(ra=0x80000000;ra;ra>>=1)
{
if(ra&rb) printf("1"); else printf("0");
}
printf("\n");
return(0);
}
gives
./so 101
0b00000000000000000000000000000101
./so 101010101
0b00000000000000000000000101010101
./so 111000111000
0b00000000000000000000111000111000
EDIT2
You really have to understand binary, ASCII, visual representations, bit manipulation, etc.
#include <stdio.h>
int main ( int argc, char *argv[])
{
unsigned int ra,rb;
if(argc<2) return(1);
rb=0;
for(ra=0;argv[1][ra];ra++)
{
rb<<=1;
rb|=argv[1][ra]&1;
}
printf("hex %08X\n",rb);
printf("octal %011o\n",rb);
printf("binary ");
for(ra=0x80000000;ra;ra>>=1)
{
if(ra&rb) printf("1"); else printf("0");
}
printf("\n");
return(0);
}
gives
./so 101010101
hex 00000155
octal 00000000525
binary 00000000000000000000000101010101
./so 111000111
hex 000001C7
octal 00000000707
binary 00000000000000000000000111000111
./so 101
hex 00000005
octal 00000000005
binary 00000000000000000000000000000101
these binary bits
000111000111
to make them easier to read and communicate can be broken into octal:
000 111 000 111
start from the right and take three at a time, this gives 0707
Or hex, start from the right take them four at a time
0001 1100 0111
this gives 1C7
But in order to "see" them the computer went back to ASCII (and this day and age that was converted into a bigger representation that includes language differences)
I manually turned the binary number 0101 into 0x31,0x30,0x31 so we could see "101". The formatted printf, 0101 became 0x35 so we could see "5", likewise the binary number 0101, became 0x30,0x35 so we could see "05".
EDIT3
#include <stdio.h>
int main ( int argc, char *argv[])
{
unsigned int ra,rb;
if(argc<2) return(1);
rb=0;
for(ra=0;argv[1][ra];ra++)
{
rb<<=1;
rb|=argv[1][ra]&1;
}
printf("binary (base 2) ");
for(ra=0x80000000;ra;ra>>=1)
{
char rc;
if(ra&rb) rc=0x31; else rc=0x30;
printf("%c",rc);
}
printf("\n");
printf("base four ");
for(ra=30;;ra-=2)
{
char rc;
rc=(rb>>ra)&3;
rc+=0x30;
printf("%c",rc);
if(ra==0) break;
}
printf("\n");
printf("octal (base 8) ");
for(ra=30;;ra-=3)
{
char rc;
rc=(rb>>ra)&7;
rc+=0x30;
printf("%c",rc);
if(ra==0) break;
}
printf("\n");
printf("hexadecimal (base 16) ");
for(ra=28;;ra-=4)
{
char rc;
rc=(rb>>ra)&0xF;
rc+=0x30;
if(rc>0x39) rc+=7;
printf("%c",rc);
if(ra==0) break;
}
printf("\n");
return(0);
}
./so 101
binary (base 2) 00000000000000000000000000000101
base four 0000000000000011
octal (base 8) 00000000005
hexadecimal (base 16) 00000005
./so 1010
binary (base 2) 00000000000000000000000000001010
base four 0000000000000022
octal (base 8) 00000000012
hexadecimal (base 16) 0000000A
./so 11001100
binary (base 2) 00000000000000000000000011001100
base four 0000000000003030
octal (base 8) 00000000314
hexadecimal (base 16) 000000CC
./so 111000111
binary (base 2) 00000000000000000000000111000111
base four 0000000000013013
octal (base 8) 00000000707
hexadecimal (base 16) 000001C7
./so 111100001111
binary (base 2) 00000000000000000000111100001111
base four 0000000000330033
octal (base 8) 00000007417
hexadecimal (base 16) 00000F0F
EDIT
#include <stdio.h>
int main ( void )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
char s[32];
rb=0x1234;
for(ra=0x8000;ra;ra>>=1)
{
printf("0x%04X & 0x%04X = 0x%04X ",ra,rb,ra&rb);
if(ra&rb) printf("1"); else printf("0");
printf("\n");
}
for(ra=0x8000;ra;ra>>=1)
{
if(ra&rb) printf("1"); else printf("0");
}
printf("\n");
for(ra=0;ra<16;ra++)
{
if((ra&3)==0) printf(" ");
if((rb>>(15-ra))&1) printf("1"); else printf("0");
}
printf("\n");
for(rc=0,ra=0x8000;ra;ra>>=1,rc++)
{
if(ra&rb) s[rc]='1'; else s[rc]='0';
}
s[rc++]='\r';
s[rc++]='\n';
s[rc]=0;
for(ra=0;s[ra];ra++)
{
printf("0x%02X ",s[ra]);
}
printf("\n");
printf("%s",s);
return(0);
}
output
0x8000 & 0x1234 = 0x0000 0
0x4000 & 0x1234 = 0x0000 0
0x2000 & 0x1234 = 0x0000 0
0x1000 & 0x1234 = 0x1000 1
0x0800 & 0x1234 = 0x0000 0
0x0400 & 0x1234 = 0x0000 0
0x0200 & 0x1234 = 0x0200 1
0x0100 & 0x1234 = 0x0000 0
0x0080 & 0x1234 = 0x0000 0
0x0040 & 0x1234 = 0x0000 0
0x0020 & 0x1234 = 0x0020 1
0x0010 & 0x1234 = 0x0010 1
0x0008 & 0x1234 = 0x0000 0
0x0004 & 0x1234 = 0x0004 1
0x0002 & 0x1234 = 0x0000 0
0x0001 & 0x1234 = 0x0000 0
0001001000110100
0001 0010 0011 0100
0x30 0x30 0x30 0x31 0x30 0x30 0x31 0x30 0x30 0x30 0x31 0x31 0x30 0x31 0x30 0x30 0x0D 0x0A
0001001000110100
In addition to the other answers, the "confused" part most likely stems from the fact that getBits will store the value in new.bits with the bits reversed. Similar to host-to-network and network-to-host byte order, but completely bitwise reversed in your case.
Where you have
struct _float {
unsigned int sign:1, exp:8, frac:23;
};
You have a single bitfield where you designate sign as the most-significant bit. In memory, on a little-endian architecture this will be bit-0, not bit-31, resulting in your manipulation in getBits of new.bits leaving new.fval and new.xval being held in memory backwards.
Now, of course, the simple fix is to reverse your bitfield, e.g.
struct _float {
unsigned int frac:23, exp:8, sign:1;
};
To illustrate the point, let's just take new and reverse the bits before return. Nothing fancy, just a loop to reverse the bits of an unsigned value, e.g.
/* reverse the bits in v, sz number of bits */
unsigned revbits (unsigned v, int sz)
{
unsigned r = 0;
for (int i = 0; i < sz; i++)
r |= ((v >> i) & 0x1) << (sz - i - 1);
return r;
}
Also, note in getBits you cannot assign the strings to the bitfield values, you must OR and shift each individual bit into the proper location within the bitfield, while subtracting '0' to convert from ASCII to integer value, for instance:
/* convert char *exp into an 8-bit value in new.bits */
for (int i = 0; i < EXP; i++)
new.bits.exp |= (exp[i] - '0') << i;
Now lets reverse the bits of new in getBits before return, e.g.
/* convert three bit-strings (already checked)
* into the components of a struct _float
*/
Union32 getBits (char *sign, char *exp, char *frac) {
Union32 new = { .xval = 0 };
/* convert char *sign into a single bit in new.bits */
new.bits.sign = *sign - '0';
/* convert char *exp into an 8-bit value in new.bits */
for (int i = 0; i < EXP; i++)
new.bits.exp |= (exp[i] - '0') << i;
/* convert char *frac into a 23-bit value in new.bits */
for (int i = 0; i < FRAC; i++)
new.bits.frac |= (frac[i] - '0') << i;
/* reverse the bit order */
new.xval = revbits (new.xval, sizeof new.xval * CHAR_BIT);
return new;
}
Now your example correctly outputs -40.015869. If you put all the pieces together, and use constants in your code, instead of sprinkling magic numbers throughout, and using CHAR_BIT from limits.h to insure we have the correct number of bit for our type, and adding a missing typedef for Word to unsigned, you could do something similar to:
#include <stdio.h>
#include <limits.h>
/* constants for use in code (don't use magic numbers) */
enum { SIGN = 1, EXP = 8, FRAC = 23 };
typedef struct _float {
unsigned sign:SIGN,
exp :EXP,
frac:FRAC;
} Float32;
typedef unsigned Word; /* you need typedef for unsigned as Word */
union _bits32 {
float fval; /* Bits as a float */
Word xval; /* Bits as a word */
Float32 bits; /* manipulate individual bits (reverse order) */
};
typedef union _bits32 Union32;
/* reverse the bits in v, sz number of bits */
unsigned revbits (unsigned v, int sz)
{
unsigned r = 0;
for (int i = 0; i < sz; i++)
r |= ((v >> i) & 0x1) << (sz - i - 1);
return r;
}
/* convert three bit-strings (already checked)
* into the components of a struct _float
*/
Union32 getBits (char *sign, char *exp, char *frac) {
Union32 new = { .xval = 0 };
/* convert char *sign into a single bit in new.bits */
new.bits.sign = *sign - '0';
/* convert char *exp into an 8-bit value in new.bits */
for (int i = 0; i < EXP; i++)
new.bits.exp |= (exp[i] - '0') << i;
/* convert char *frac into a 23-bit value in new.bits */
for (int i = 0; i < FRAC; i++)
new.bits.frac |= (frac[i] - '0') << i;
/* reverse the bit order */
new.xval = revbits (new.xval, sizeof new.xval * CHAR_BIT);
return new;
}
int main (int argc, char **argv) {
union _bits32 u = { .xval = 0 };
/* set u (default value is PI to 3.14159) */
u = getBits (argc > 1 ? argv[1] : "0",
argc > 2 ? argv[2] : "10000000",
argc > 3 ? argv[3] : "10010010000111111010000");
/* output fval */
printf ("u.fval %f\n", u.fval);
return 0;
}
Example Use/Output
Default case with PI:
$ ./bin/floatbits
u.fval 3.141590
Using your input:
$ ./bin/floatbits 1 10000100 01000000001000001000000
u.fval -40.015869
Rearranging the Order of Float32
As mentioned above, rather than reversing the bits before return in getBits, the more straight forward approach is to change the order of Float32 so that you have the bitfield order as FRAC, EXP, SIGN which would make the order in-memory of bits consistent with fval and xval.
Now you can simply fill each in getBit (while taking care to fill the bits in proper bit order for your host, e.g. little-endian, least significant bit is highest bit in range, etc.). This simply requires you recognizing that string[0] will map to bit[most-significant] for each of FRAC and EXP. With that change, the code would simplify to:
#include <stdio.h>
/* constants for use in code (don't use magic numbers) */
enum { SIGN = 1, EXP = 8, FRAC = 23 };
typedef struct _float {
unsigned frac:FRAC,
exp :EXP,
sign:SIGN;
} Float32;
typedef unsigned Word; /* you need typedef for unsigned as Word */
union _bits32 {
float fval; /* Bits as a float */
Word xval; /* Bits as a word */
Float32 bits; /* manipulate individual bits (reverse order) */
};
typedef union _bits32 Union32;
/* convert three bit-strings (already checked)
* into the components of a struct _float
*/
Union32 getBits (char *sign, char *exp, char *frac) {
Union32 new = { .xval = 0 };
/* convert char *sign into a single bit in new.bits */
new.bits.sign = *sign - '0';
/* convert char *exp into an 8-bit value in new.bits */
for (int i = 0; i < EXP; i++)
new.bits.exp |= (exp[EXP - i - 1] - '0') << i;
/* convert char *frac into a 23-bit value in new.bits */
for (int i = 0; i < FRAC; i++)
new.bits.frac |= (frac[FRAC - i - 1] - '0') << i;
return new;
}
int main (int argc, char **argv) {
union _bits32 u = { .xval = 0 };
/* set u (default value is PI to 3.14159) */
u = getBits (argc > 1 ? argv[1] : "0",
argc > 2 ? argv[2] : "10000000",
argc > 3 ? argv[3] : "10010010000111111010000");
/* output fval */
printf ("u.fval %f\n", u.fval);
return 0;
}
(the use/output is the same)
While bitfields are fine to learn, they are rarely portable. If your goal is portable code, then they are best avoided.
Let me know if you have questions.
#include <stdio.h>
int main () {
for (char ch = 'A'; ch <= 'Z'; ++ch) {
printf("%d\t", ch);
}
for (char ch = 'a'; ch <= 'z'; ++ch) {
printf("%d\t", ch);
}
return 0;
}

Decimal to BCD to ASCII

Perhaps this task is a bit more complicated than what I've written below, but the code that follows is my take on decimal to BCD. The task is to take in a decimal number, convert it to BCD and then to ASCII so that it can be displayed on a microcontroller. As far as I'm aware the code works sufficiently for the basic operation of converting to BCD however I'm stuck when it comes to converting this into ASCII. The overall output is ASCII so that an incremented value can be displayed on an LCD.
My code so far:
int dec2bin(int a){ //Decimal to binary function
int bin;
int i =1;
while (a!=0){
bin+=(a%2)*i;
i*=10;
a/=2;
}
return bin;
}
unsigned int ConverttoBCD(int val){
unsigned int unit = 0;
unsigned int ten = 0;
unsigned int hundred = 0;
hundred = (val/100);
ten = ((val-hundred*100)/10);
unit = (val-(hundred*100+ten*10));
uint8_t ret1 = dec2bin(unit);
uint8_t ret2 = dec2bin((ten)<<4);
uint8_t ret3 = dec2bin((hundred)<<8);
return(ret3+ret2+ret1);
}
The idea to convert to BCD for an ASCII representation of a number is actually the "correct one". Given BCD, you only need to add '0' to each digit for getting the corresponding ASCII value.
But your code has several problems. The most important one is that you try to stuff a value shifted left by 8 bits in an 8bit type. This can never work, those 8 bits will be zero, think about it! Then I absolutely do not understand what your dec2bin() function is supposed to do.
So I'll present you one possible correct solution to your problem. The key idea is to use a char for each individual BCD digit. Of course, a BCD digit only needs 4 bits and a char has at least 8 of them -- but you need char anyways for your ASCII representation and when your BCD digits are already in individual chars, all you have to do is indeed add '0' to each.
While at it: Converting to BCD by dividing and multiplying is a waste of resources. There's a nice algorithm called Double dabble for converting to BCD only using bit shifting and additions. I'm using it in the following example code:
#include <stdio.h>
#include <string.h>
// for determining the number of value bits in an integer type,
// see https://stackoverflow.com/a/4589384/2371524 for this nice trick:
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
// number of bits in unsigned int:
#define UNSIGNEDINT_BITS IMAX_BITS((unsigned)-1)
// convert to ASCII using BCD, return the number of digits:
int toAscii(char *buf, int bufsize, unsigned val)
{
// sanity check, a buffer smaller than one digit is pointless
if (bufsize < 1) return -1;
// initialize output buffer to zero
// if you don't have memset, use a loop here
memset(buf, 0, bufsize);
int scanstart = bufsize - 1;
int i;
// mask for single bits in value, start at most significant bit
unsigned mask = 1U << (UNSIGNEDINT_BITS - 1);
while (mask)
{
// extract single bit
int bit = !!(val & mask);
for (i = scanstart; i < bufsize; ++i)
{
// this is the "double dabble" trick -- in each iteration,
// add 3 to each element that is greater than 4. This will
// generate the correct overflowing bits while shifting for
// BCD
if (buf[i] > 4) buf[i] += 3;
}
// if we have filled the output buffer from the right far enough,
// we have to scan one position earlier in the next iteration
if (buf[scanstart] > 7) --scanstart;
// check for overflow of our buffer:
if (scanstart < 0) return -1;
// now just shift the bits in the BCD digits:
for (i = scanstart; i < bufsize - 1; ++i)
{
buf[i] <<= 1;
buf[i] &= 0xf;
buf[i] |= (buf[i+1] > 7);
}
// shift in the new bit from our value:
buf[bufsize-1] <<= 1;
buf[bufsize-1] &= 0xf;
buf[bufsize-1] |= bit;
// next bit:
mask >>= 1;
}
// find first non-zero digit:
for (i = 0; i < bufsize - 1; ++i) if (buf[i]) break;
int digits = bufsize - i;
// eliminate leading zero digits
// (again, use a loop if you don't have memmove)
// (or, if you're converting to a fixed number of digits and *want*
// the leading zeros, just skip this step entirely, including the
// loop above)
memmove(buf, buf + i, digits);
// convert to ascii:
for (i = 0; i < digits; ++i) buf[i] += '0';
return digits;
}
int main(void)
{
// some simple test code:
char buf[10];
int digits = toAscii(buf, 10, 471142);
for (int i = 0; i < digits; ++i)
{
putchar(buf[i]);
}
puts("");
}
You won't need this IMAX_BITS() "magic macro" if you actually know your target platform and how many bits there are in the integer type you want to convert.

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

Is there a printf converter to print in binary format?

I can print with printf as a hex or octal number. Is there a format tag to print as binary, or arbitrary base?
I am running gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
printf("%b\n", 10); // prints "%b\n"
Hacky but works for me:
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
printf("Leading text "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));
For multi-byte types
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
You need all the extra quotes unfortunately. This approach has the efficiency risks of macros (don't pass a function as the argument to BYTE_TO_BINARY) but avoids the memory issues and multiple invocations of strcat in some of the other proposals here.
Print Binary for Any Datatype
// Assumes little endian
void printBits(size_t const size, void const * const ptr)
{
unsigned char *b = (unsigned char*) ptr;
unsigned char byte;
int i, j;
for (i = size-1; i >= 0; i--) {
for (j = 7; j >= 0; j--) {
byte = (b[i] >> j) & 1;
printf("%u", byte);
}
}
puts("");
}
Test:
int main(int argv, char* argc[])
{
int i = 23;
uint ui = UINT_MAX;
float f = 23.45f;
printBits(sizeof(i), &i);
printBits(sizeof(ui), &ui);
printBits(sizeof(f), &f);
return 0;
}
Here is a quick hack to demonstrate techniques to do what you want.
#include <stdio.h> /* printf */
#include <string.h> /* strcat */
#include <stdlib.h> /* strtol */
const char *byte_to_binary
(
int x
)
{
static char b[9];
b[0] = '\0';
int z;
for (z = 128; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
int main
(
void
)
{
{
/* binary string to int */
char *tmp;
char *b = "0101";
printf("%d\n", strtol(b, &tmp, 2));
}
{
/* byte to binary string */
printf("%s\n", byte_to_binary(5));
}
return 0;
}
There isn't a binary conversion specifier in glibc normally.
It is possible to add custom conversion types to the printf() family of functions in glibc. See register_printf_function for details. You could add a custom %b conversion for your own use, if it simplifies the application code to have it available.
Here is an example of how to implement a custom printf formats in glibc.
You could use a small table to improve speed1. Similar techniques are useful in the embedded world, for example, to invert a byte:
const char *bit_rep[16] = {
[ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011",
[ 4] = "0100", [ 5] = "0101", [ 6] = "0110", [ 7] = "0111",
[ 8] = "1000", [ 9] = "1001", [10] = "1010", [11] = "1011",
[12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
};
void print_byte(uint8_t byte)
{
printf("%s%s", bit_rep[byte >> 4], bit_rep[byte & 0x0F]);
}
1 I'm mostly referring to embedded applications where optimizers are not so aggressive and the speed difference is visible.
Print the least significant bit and shift it out on the right. Doing this until the integer becomes zero prints the binary representation without leading zeros but in reversed order. Using recursion, the order can be corrected quite easily.
#include <stdio.h>
void print_binary(unsigned int number)
{
if (number >> 1) {
print_binary(number >> 1);
}
putc((number & 1) ? '1' : '0', stdout);
}
To me, this is one of the cleanest solutions to the problem. If you like 0b prefix and a trailing new line character, I suggest wrapping the function.
Online demo
Based on #William Whyte's answer, this is a macro that provides int8,16,32 & 64 versions, reusing the INT8 macro to avoid repetition.
/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i) \
(((i) & 0x80ll) ? '1' : '0'), \
(((i) & 0x40ll) ? '1' : '0'), \
(((i) & 0x20ll) ? '1' : '0'), \
(((i) & 0x10ll) ? '1' : '0'), \
(((i) & 0x08ll) ? '1' : '0'), \
(((i) & 0x04ll) ? '1' : '0'), \
(((i) & 0x02ll) ? '1' : '0'), \
(((i) & 0x01ll) ? '1' : '0')
#define PRINTF_BINARY_PATTERN_INT16 \
PRINTF_BINARY_PATTERN_INT8 PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
PRINTF_BYTE_TO_BINARY_INT8((i) >> 8), PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
PRINTF_BINARY_PATTERN_INT16 PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64 \
PRINTF_BINARY_PATTERN_INT32 PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */
#include <stdio.h>
int main() {
long long int flag = 1648646756487983144ll;
printf("My Flag "
PRINTF_BINARY_PATTERN_INT64 "\n",
PRINTF_BYTE_TO_BINARY_INT64(flag));
return 0;
}
This outputs:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
For readability you may want to add a separator for eg:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
As of February 3rd, 2022, the GNU C Library been updated to version 2.35. As a result, %b is now supported to output in binary format.
printf-family functions now support the %b format for output of
integers in binary, as specified in draft ISO C2X, and the %B variant
of that format recommended by draft ISO C2X.
Here's a version of the function that does not suffer from reentrancy issues or limits on the size/type of the argument:
#define FMT_BUF_SIZE (CHAR_BIT*sizeof(uintmax_t)+1)
char *binary_fmt(uintmax_t x, char buf[static FMT_BUF_SIZE])
{
char *s = buf + FMT_BUF_SIZE;
*--s = 0;
if (!x) *--s = '0';
for (; x; x /= 2) *--s = '0' + x%2;
return s;
}
Note that this code would work just as well for any base between 2 and 10 if you just replace the 2's by the desired base. Usage is:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
Where x is any integral expression.
Quick and easy solution:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Works for any size type and for signed and unsigned ints. The '&1' is needed to handle signed ints as the shift may do sign extension.
There are so many ways of doing this. Here's a super simple one for printing 32 bits or n bits from a signed or unsigned 32 bit type (not putting a negative if signed, just printing the actual bits) and no carriage return. Note that i is decremented before the bit shift:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
What about returning a string with the bits to store or print later? You either can allocate the memory and return it and the user has to free it, or else you return a static string but it will get clobbered if it's called again, or by another thread. Both methods shown:
char *int_to_bitstring_alloc(int x, int count)
{
count = count<1 ? sizeof(x)*8 : count;
char *pstr = malloc(count+1);
for(int i = 0; i<count; i++)
pstr[i] = '0' | ((x>>(count-1-i))&1);
pstr[count]=0;
return pstr;
}
#define BITSIZEOF(x) (sizeof(x)*8)
char *int_to_bitstring_static(int x, int count)
{
static char bitbuf[BITSIZEOF(x)+1];
count = (count<1 || count>BITSIZEOF(x)) ? BITSIZEOF(x) : count;
for(int i = 0; i<count; i++)
bitbuf[i] = '0' | ((x>>(count-1-i))&1);
bitbuf[count]=0;
return bitbuf;
}
Call with:
// memory allocated string returned which needs to be freed
char *pstr = int_to_bitstring_alloc(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr);
free(pstr);
// no free needed but you need to copy the string to save it somewhere else
char *pstr2 = int_to_bitstring_static(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr2);
Is there a printf converter to print in binary format?
The printf() family is only able to print integers in base 8, 10, and 16 using the standard specifiers directly. I suggest creating a function that converts the number to a string per code's particular needs.
[Edit 2022] This is expected to change with the next version of C which implements "%b".
Binary constants such as 0b10101010, and %b conversion specifier for printf() function family C2x
To print in any base [2-36]
All other answers so far have at least one of these limitations.
Use static memory for the return buffer. This limits the number of times the function may be used as an argument to printf().
Allocate memory requiring the calling code to free pointers.
Require the calling code to explicitly provide a suitable buffer.
Call printf() directly. This obliges a new function for to fprintf(), sprintf(), vsprintf(), etc.
Use a reduced integer range.
The following has none of the above limitation. It does require C99 or later and use of "%s". It uses a compound literal to provide the buffer space. It has no trouble with multiple calls in a printf().
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)
// v--compound literal--v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
// Tailor the details of the conversion function as needed
// This one does not display unneeded leading zeros
// Use return value, not `buf`
char *my_to_base(char buf[TO_BASE_N], unsigned i, int base) {
assert(base >= 2 && base <= 36);
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % base];
i /= base;
} while (i);
// Could employ memmove here to move the used buffer to the beginning
// size_t len = &buf[TO_BASE_N] - s;
// memmove(buf, s, len);
return s;
}
#include <stdio.h>
int main(void) {
int ip1 = 0x01020304;
int ip2 = 0x05060708;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
return 0;
}
Output
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
const char* byte_to_binary(int x)
{
static char b[sizeof(int)*8+1] = {0};
int y;
long long z;
for (z = 1LL<<sizeof(int)*8-1, y = 0; z > 0; z >>= 1, y++) {
b[y] = (((x & z) == z) ? '1' : '0');
}
b[y] = 0;
return b;
}
None of the previously posted answers are exactly what I was looking for, so I wrote one. It is super simple to use %B with the printf!
/*
* File: main.c
* Author: Techplex.Engineer
*
* Created on February 14, 2012, 9:16 PM
*/
#include <stdio.h>
#include <stdlib.h>
#include <printf.h>
#include <math.h>
#include <string.h>
static int printf_arginfo_M(const struct printf_info *info, size_t n, int *argtypes)
{
/* "%M" always takes one argument, a pointer to uint8_t[6]. */
if (n > 0) {
argtypes[0] = PA_POINTER;
}
return 1;
}
static int printf_output_M(FILE *stream, const struct printf_info *info, const void *const *args)
{
int value = 0;
int len;
value = *(int **) (args[0]);
// Beginning of my code ------------------------------------------------------------
char buffer [50] = ""; // Is this bad?
char buffer2 [50] = ""; // Is this bad?
int bits = info->width;
if (bits <= 0)
bits = 8; // Default to 8 bits
int mask = pow(2, bits - 1);
while (mask > 0) {
sprintf(buffer, "%s", ((value & mask) > 0 ? "1" : "0"));
strcat(buffer2, buffer);
mask >>= 1;
}
strcat(buffer2, "\n");
// End of my code --------------------------------------------------------------
len = fprintf(stream, "%s", buffer2);
return len;
}
int main(int argc, char** argv)
{
register_printf_specifier('B', printf_output_M, printf_arginfo_M);
printf("%4B\n", 65);
return EXIT_SUCCESS;
}
This code should handle your needs up to 64 bits.
I created two functions: pBin and pBinFill. Both do the same thing, but pBinFill fills in the leading spaces with the fill character provided by its last argument.
The test function generates some test data, then prints it out using the pBinFill function.
#define kDisplayWidth 64
char* pBin(long int x,char *so)
{
char s[kDisplayWidth+1];
int i = kDisplayWidth;
s[i--] = 0x00; // terminate string
do { // fill in array from right to left
s[i--] = (x & 1) ? '1' : '0'; // determine bit
x >>= 1; // shift right 1 bit
} while (x > 0);
i++; // point to last valid character
sprintf(so, "%s", s+i); // stick it in the temp string string
return so;
}
char* pBinFill(long int x, char *so, char fillChar)
{
// fill in array from right to left
char s[kDisplayWidth+1];
int i = kDisplayWidth;
s[i--] = 0x00; // terminate string
do { // fill in array from right to left
s[i--] = (x & 1) ? '1' : '0';
x >>= 1; // shift right 1 bit
} while (x > 0);
while (i >= 0) s[i--] = fillChar; // fill with fillChar
sprintf(so, "%s", s);
return so;
}
void test()
{
char so[kDisplayWidth+1]; // working buffer for pBin
long int val = 1;
do {
printf("%ld =\t\t%#lx =\t\t0b%s\n", val, val, pBinFill(val, so, '0'));
val *= 11; // generate test data
} while (val < 100000000);
}
Output:
00000001 = 0x000001 = 0b00000000000000000000000000000001
00000011 = 0x00000b = 0b00000000000000000000000000001011
00000121 = 0x000079 = 0b00000000000000000000000001111001
00001331 = 0x000533 = 0b00000000000000000000010100110011
00014641 = 0x003931 = 0b00000000000000000011100100110001
00161051 = 0x02751b = 0b00000000000000100111010100011011
01771561 = 0x1b0829 = 0b00000000000110110000100000101001
19487171 = 0x12959c3 = 0b00000001001010010101100111000011
Some runtimes support "%b" although that is not a standard.
Also see here for an interesting discussion:
http://bytes.com/forum/thread591027.html
HTH
Maybe a bit OT, but if you need this only for debuging to understand or retrace some binary operations you are doing, you might take a look on wcalc (a simple console calculator). With the -b options you get binary output.
e.g.
$ wcalc -b "(256 | 3) & 0xff"
= 0b11
There is no formatting function in the C standard library to output binary like that. All the format operations the printf family supports are towards human readable text.
The following recursive function might be useful:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
I optimized the top solution for size and C++-ness, and got to this solution:
inline std::string format_binary(unsigned int x)
{
static char b[33];
b[32] = '\0';
for (int z = 0; z < 32; z++) {
b[31-z] = ((x>>z) & 0x1) ? '1' : '0';
}
return b;
}
Use:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
For more ref., see How to print binary number via printf.
void
print_binary(unsigned int n)
{
unsigned int mask = 0;
/* this grotesque hack creates a bit pattern 1000... */
/* regardless of the size of an unsigned int */
mask = ~mask ^ (~mask >> 1);
for(; mask != 0; mask >>= 1) {
putchar((n & mask) ? '1' : '0');
}
}
Print bits from any type using less code and resources
This approach has as attributes:
Works with variables and literals.
Doesn't iterate all bits when not necessary.
Call printf only when complete a byte (not unnecessarily for all bits).
Works for any type.
Works with little and big endianness (uses GCC #defines for checking).
May work with hardware that char isn't a byte (eight bits). (Tks #supercat)
Uses typeof() that isn't C standard but is largely defined.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define for_endian(size) for (int i = 0; i < size; ++i)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define for_endian(size) for (int i = size - 1; i >= 0; --i)
#else
#error "Endianness not detected"
#endif
#define printb(value) \
({ \
typeof(value) _v = value; \
__printb((typeof(_v) *) &_v, sizeof(_v)); \
})
#define MSB_MASK 1 << (CHAR_BIT - 1)
void __printb(void *value, size_t size)
{
unsigned char uc;
unsigned char bits[CHAR_BIT + 1];
bits[CHAR_BIT] = '\0';
for_endian(size) {
uc = ((unsigned char *) value)[i];
memset(bits, '0', CHAR_BIT);
for (int j = 0; uc && j < CHAR_BIT; ++j) {
if (uc & MSB_MASK)
bits[j] = '1';
uc <<= 1;
}
printf("%s ", bits);
}
printf("\n");
}
int main(void)
{
uint8_t c1 = 0xff, c2 = 0x44;
uint8_t c3 = c1 + c2;
printb(c1);
printb((char) 0xff);
printb((short) 0xff);
printb(0xff);
printb(c2);
printb(0x44);
printb(0x4411ff01);
printb((uint16_t) c3);
printb('A');
printf("\n");
return 0;
}
Output
$ ./printb
11111111
11111111
00000000 11111111
00000000 00000000 00000000 11111111
01000100
00000000 00000000 00000000 01000100
01000100 00010001 11111111 00000001
00000000 01000011
00000000 00000000 00000000 01000001
I have used another approach (bitprint.h) to fill a table with all bytes (as bit strings) and print them based on the input/index byte. It's worth taking a look.
Maybe someone will find this solution useful:
void print_binary(int number, int num_digits) {
int digit;
for(digit = num_digits - 1; digit >= 0; digit--) {
printf("%c", number & (1 << digit) ? '1' : '0');
}
}
void print_ulong_bin(const unsigned long * const var, int bits) {
int i;
#if defined(__LP64__) || defined(_LP64)
if( (bits > 64) || (bits <= 0) )
#else
if( (bits > 32) || (bits <= 0) )
#endif
return;
for(i = 0; i < bits; i++) {
printf("%lu", (*var >> (bits - 1 - i)) & 0x01);
}
}
should work - untested.
I liked the code by paniq, the static buffer is a good idea. However it fails if you want multiple binary formats in a single printf() because it always returns the same pointer and overwrites the array.
Here's a C style drop-in that rotates pointer on a split buffer.
char *
format_binary(unsigned int x)
{
#define MAXLEN 8 // width of output format
#define MAXCNT 4 // count per printf statement
static char fmtbuf[(MAXLEN+1)*MAXCNT];
static int count = 0;
char *b;
count = count % MAXCNT + 1;
b = &fmtbuf[(MAXLEN+1)*count];
b[MAXLEN] = '\0';
for (int z = 0; z < MAXLEN; z++) { b[MAXLEN-1-z] = ((x>>z) & 0x1) ? '1' : '0'; }
return b;
}
Here is a small variation of paniq's solution that uses templates to allow printing of 32 and 64 bit integers:
template<class T>
inline std::string format_binary(T x)
{
char b[sizeof(T)*8+1] = {0};
for (size_t z = 0; z < sizeof(T)*8; z++)
b[sizeof(T)*8-1-z] = ((x>>z) & 0x1) ? '1' : '0';
return std::string(b);
}
And can be used like:
unsigned int value32 = 0x1e127ad;
printf( " 0x%x: %s\n", value32, format_binary(value32).c_str() );
unsigned long long value64 = 0x2e0b04ce0;
printf( "0x%llx: %s\n", value64, format_binary(value64).c_str() );
Here is the result:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000
No standard and portable way.
Some implementations provide itoa(), but it's not going to be in most, and it has a somewhat crummy interface. But the code is behind the link and should let you implement your own formatter pretty easily.
I just want to post my solution. It's used to get zeroes and ones of one byte, but calling this function few times can be used for larger data blocks. I use it for 128 bit or larger structs. You can also modify it to use size_t as input parameter and pointer to data you want to print, so it can be size independent. But it works for me quit well as it is.
void print_binary(unsigned char c)
{
unsigned char i1 = (1 << (sizeof(c)*8-1));
for(; i1; i1 >>= 1)
printf("%d",(c&i1)!=0);
}
void get_binary(unsigned char c, unsigned char bin[])
{
unsigned char i1 = (1 << (sizeof(c)*8-1)), i2=0;
for(; i1; i1>>=1, i2++)
bin[i2] = ((c&i1)!=0);
}
Here's how I did it for an unsigned int
void printb(unsigned int v) {
unsigned int i, s = 1<<((sizeof(v)<<3)-1); // s = only most significant bit at 1
for (i = s; i; i>>=1) printf("%d", v & i || 0 );
}
One statement generic conversion of any integral type into the binary string representation using standard library:
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
Or just: std::cout << std::bitset<sizeof(num) * 8>(num);

Resources