Brian
Brian

Reputation: 8823

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"

Upvotes: 615

Views: 1325329

Answers (30)

Sajidur Rahman
Sajidur Rahman

Reputation: 3060

Bit-masking can be used to print the binary values:

void int_to_bin(int num) {
  for (int i = (sizeof(int) * 8) - 1; i >= 0; i--) {
    int bit = (num >> i) & 1;

    printf("%d", bit);

    if (i % 8 == 0) {
      printf(" ");
    }
  }
  printf("\n");
}

Usage:

int main() {
  int x = 1000000000;

  int_to_bin(x);
  
  return 0;
}

Output:

00111011 10011010 11001010 00000000

Upvotes: 0

Nikola
Nikola

Reputation: 125

I have to add my solution, because every time I am searching for the answer I end up writing my own function because all the answers here are semi-solutions and I like this solution the most:

#define INT_SIZE 32

void PrintBinary(int num){
    char arr[INT_SIZE+1];
    for (int i = 0; i<INT_SIZE; ++i){
        arr[i] = '0';
    }
    arr[INT_SIZE] = 0;
    int ind = INT_SIZE;
    while(num){
        arr[--ind] = (num & 1)?'1':'0';
        num >>=1;
    }
    printf("%d = %s", num, arr);
}

Upvotes: 0

user295190
user295190

Reputation:

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 argc, char* argv[])
{
    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;
}

Upvotes: 246

Ravi
Ravi

Reputation: 143

Not sure why the following hasn't been proposed yet:

#include <stdio.h>
int main()
{
    int n = 156;
    printf(" n_dec: %d\n n_bin: %08b\n", n, n);
    return 0;
}

Output:

ubuntu@server:~$ ./a.out
 n_dec: 156
 n_bin: 10011100
ubuntu@server:~$

Upvotes: 5

RARE Kpop Manifesto
RARE Kpop Manifesto

Reputation: 2809

You don't need to physically even enumerate the bits to generate all the bit-strings for a lookup table -

  • given an integer n := [0, 4] as input, it would enumerate all permutations of bit-strings for 2 ** n bits, in pre-sorted order, using nothing but regular expressions (regex)

    — enumerating every base4 pair of bits is n = 1, — enumerating every base16 hex is n = 2, — enumerating every byte is n = 3, since 2 ^ 3 = 8 — enumerating every short-int is n = 4

(even the 64GB ram on my laptop couldn't handle an input of 5, which would, theoretically return every single 4-byte bit string permutation, with a resulting output at least 128 GB in size … via just 5 cycles of a while() loop)


     out9:  667 B 0:00:00 [17.7MiB/s] [17.7MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 0 ) = 
                                all permutations of 1-bit bit-strings
    4
    0, 1
    0, 1
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     3      # BEGIN rule(s)

     4      BEGIN {
     5       1      OFS = "\f\r\t"
     6       1      print " \f\t" (_ += _ ^= _ < _) " ^ " (_)\
                          " ^ ( " (+__) " ) = \fall permutations of "\
                          (_++ ^ __) "-bit bit-strings", 

                           _____ = length(___ = ____(__)), 
                          substr(___,__ = !!++_,_ *= _*_),
                          substr(___,_____  + __ - _), ""
     7      }


     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) {
    12                  while (__--) {
    13                      gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18      }
( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 64% cpu 0.007 total

     out9:  706 B 0:00:00 [25.9MiB/s] [25.9MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 1 ) = 
                                all permutations of 2-bit bit-strings
    14
    00, 01, 10, 11
    00, 01, 10, 11
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10      {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       1          while (__--) {
    13       1              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18         }
    ( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 63% cpu 0.007 total

     out9:  806 B 0:00:00 [28.5MiB/s] [28.5MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 2 ) = 
                                all permutations of 4-bit bit-strings
    94
    0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111, 1000, 1001, 1010
    0101, 0110, 0111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
    
     2      # gawk profile, created Wed May 17 00:50:19 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       2          while (__--) {
    13       2              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 63% cpu 0.006 total

     out9:  808 B 0:00:00 [18.3MiB/s] [18.3MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 3 ) = 
                                all permutations of 8-bit bit-strings
    2558
    00000000, 00000001, 00000010, 00000011, 00000100, 00000101, 0000
    1001, 11111010, 11111011, 11111100, 11111101, 11111110, 11111111
    
     2      # gawk profile, created Wed May 17 00:50:20 2023

     8      # Functions, listed alphabetically

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       3          while (__--) {
    13       3              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
     ( gawk -v __="$__" -p- -be ; )  0.00s user 0.00s system 62% cpu 0.007 total

     out9:  812 B 0:00:00 [22.8MiB/s] [22.8MiB/s] [<=> ]
     1   
            2 ^ 2 ^ ( 4 ) = 
                                all permutations of 16-bit bit-strings
    1179646
    0000000000000000, 0000000000000001, 0000000000000010, 0000000000
    1111111100, 1111111111111101, 1111111111111110, 1111111111111111
    
     2      # gawk profile, created Wed May 17 00:50:20 2023

     9       1  function ____(__, _, ___)
    10          {
    11       1      if (+(_ = "&0&1") < (__ += ___ = "[&][01]+")) { # 1
    12       4          while (__--) {
    13       4              gsub(___, _, _)
    14                  }
    15              }
    16       1      gsub(__ = "[&]", ", ", _)
    17       1      return substr(_, length(__))
    18          }
    ( gawk -v __="$__" -p- -be ; )  0.01s user 0.00s system 80% cpu 0.013 total

To generate them in bit-inverted manner, change the starting point from _ = "&0&1" —> _ = "&1&0" ::

    2 ^ 2 ^ ( 2 ) = 
                      all permutations of 4-bit bit-strings
    94
    1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000, 0111, 0110, 0101
    1010, 1001, 1000, 0111, 0110, 0101, 0100, 0011, 0010, 0001, 0000

To generate them in a bit-reflected manner (e.g. for CRC), change both

  • _ = "&0&1" —> _ = "0&1&" , and also ___ = "[&][01]+" —> ___ = "[01]+[&]"
     out9:  200 B 0:00:00 [5.61MiB/s] [5.61MiB/s] [<=> ]
 
    2 ^ 2 ^ ( 2 ) = 
                        all permutations of 4-bit bit-strings
    94
    0000, 1000, 0100, 1100, 0010, 1010, 0110, 1110, 0001, 1001, 0101
    1010, 0110, 1110, 0001, 1001, 0101, 1101, 0011, 1011, 0111, 1111
    
  ( mawk2 -v __="$__" -- ; )  0.00s user 0.00s system 71% cpu 0.004 total

Upvotes: 0

William Whyte
William Whyte

Reputation: 4981

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.

Upvotes: 404

Blue Phoenix
Blue Phoenix

Reputation: 151

As for me, I wrote some general code for this

#include<stdio.h>
void int2bin(int n, int* bin, int* bin_size, const int  bits);

int main()
{
    char ch;
    ch = 'A';
    int binary[32];
    int binary_size = 0;
    
    int2bin(1324, binary, &binary_size, 32);
    for (int i = 0; i < 32; i++)
    {
        printf("%d  ", binary[i]);
    }
    
    
    return 0;
}

void int2bin(int n, int* bin,int *bin_size,const int  bits)
{
    int i = 0;
    int temp[64];
    for (int j = 0; j < 64; j++)
    {
        temp[j] = 0;
    }
    for (int l = 0; l < bits; l++)
    {
        bin[l] = 0;
    }

    while (n > 0)
    {
        temp[i] = n % 2;
        n = n / 2;
        i++;
    }
    *bin_size = i;

    //reverse modulus values
    for (int k = 0; k < *bin_size; k++)
    {
        bin[bits-*bin_size+k] = temp[*bin_size - 1 - k];
    }
}

Upvotes: 0

chux
chux

Reputation: 153303

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.

  1. Use static memory for the return buffer. This limits the number of times the function may be used as an argument to printf().

  2. Allocate memory requiring the calling code to free pointers.

  3. Require the calling code to explicitly provide a suitable buffer.

  4. Call printf() directly. This obliges a new function for to fprintf(), sprintf(), vsprintf(), etc.

  5. 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

Upvotes: 16

Kalcifer
Kalcifer

Reputation: 1600

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.

Upvotes: 62

roylewilliam
roylewilliam

Reputation: 35

Simple, tested, works for any unsigned integer type. No headaches.

#include <stdint.h>
#include <stdio.h>

// Prints the binary representation of any unsigned integer
// When running, pass 1 to first_call
void printf_binary(unsigned int number, int first_call)
{
        if (first_call)
        {
                printf("The binary representation of %d is [", number);
        }
        if (number >> 1)
        {
                printf_binary(number >> 1, 0);
                putc((number & 1) ? '1' : '0', stdout);
        }
        else 
        {
                putc((number & 1) ? '1' : '0', stdout);
        }
        if (first_call)
        {
                printf("]\n");
        }
}

Upvotes: 0

Geyslan Greg&#243;rio
Geyslan Greg&#243;rio

Reputation: 1122

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.

Upvotes: 5

EvilTeach
EvilTeach

Reputation: 28837

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

Upvotes: 168

D.Deriso
D.Deriso

Reputation: 4397

Main.c

// Based on https://stackoverflow.com/a/112956/1438550

#include <stdio.h>
#include <stdint.h>

const char *int_to_binary_str(int x, int N_bits){
    static char b[512];
    char *p = b;
    b[0] = '\0';

    for(int i=(N_bits-1); i>=0; i--){
      *p++ = (x & (1<<i)) ? '1' : '0';
      if(!(i%4)) *p++ = ' ';
    }
    return b;
}

int main() {
  for(int i=31; i>=0; i--){
    printf("0x%08X %s \n", (1<<i), int_to_binary_str((1<<i), 32));
  }
  return 0;
}

Expected behavior:

Run:
gcc -pthread -Wformat=0 -lm -o main main.c; ./main

Output:
0x80000000 1000 0000 0000 0000 0000 0000 0000 0000  
0x40000000 0100 0000 0000 0000 0000 0000 0000 0000  
0x20000000 0010 0000 0000 0000 0000 0000 0000 0000  
0x10000000 0001 0000 0000 0000 0000 0000 0000 0000  
0x08000000 0000 1000 0000 0000 0000 0000 0000 0000  
0x04000000 0000 0100 0000 0000 0000 0000 0000 0000  
0x02000000 0000 0010 0000 0000 0000 0000 0000 0000  
0x01000000 0000 0001 0000 0000 0000 0000 0000 0000  
0x00800000 0000 0000 1000 0000 0000 0000 0000 0000  
0x00400000 0000 0000 0100 0000 0000 0000 0000 0000  
0x00200000 0000 0000 0010 0000 0000 0000 0000 0000  
0x00100000 0000 0000 0001 0000 0000 0000 0000 0000  
0x00080000 0000 0000 0000 1000 0000 0000 0000 0000  
0x00040000 0000 0000 0000 0100 0000 0000 0000 0000  
0x00020000 0000 0000 0000 0010 0000 0000 0000 0000  
0x00010000 0000 0000 0000 0001 0000 0000 0000 0000  
0x00008000 0000 0000 0000 0000 1000 0000 0000 0000  
0x00004000 0000 0000 0000 0000 0100 0000 0000 0000  
0x00002000 0000 0000 0000 0000 0010 0000 0000 0000  
0x00001000 0000 0000 0000 0000 0001 0000 0000 0000  
0x00000800 0000 0000 0000 0000 0000 1000 0000 0000  
0x00000400 0000 0000 0000 0000 0000 0100 0000 0000  
0x00000200 0000 0000 0000 0000 0000 0010 0000 0000  
0x00000100 0000 0000 0000 0000 0000 0001 0000 0000  
0x00000080 0000 0000 0000 0000 0000 0000 1000 0000  
0x00000040 0000 0000 0000 0000 0000 0000 0100 0000  
0x00000020 0000 0000 0000 0000 0000 0000 0010 0000  
0x00000010 0000 0000 0000 0000 0000 0000 0001 0000  
0x00000008 0000 0000 0000 0000 0000 0000 0000 1000  
0x00000004 0000 0000 0000 0000 0000 0000 0000 0100  
0x00000002 0000 0000 0000 0000 0000 0000 0000 0010  
0x00000001 0000 0000 0000 0000 0000 0000 0000 0001 

Upvotes: 0

skyfire
skyfire

Reputation: 247

void print_bits (uintmax_t n)
{
    for (size_t i = 8 * sizeof (int); i-- != 0;)
    {
        char c;
        if ((n & (1UL << i)) != 0)
            c = '1';
        else
            c = '0';

        printf ("%c", c);

    }
}

Not a cover-absolutely-everywhere solution but if you want something quick, and easy to understand, I'm suprised no one has proposed this solution yet.

Upvotes: 1

mrwes
mrwes

Reputation: 639

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

Upvotes: 10

TechplexEngineer
TechplexEngineer

Reputation: 1928

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

Upvotes: 12

works better
works better

Reputation:

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

Upvotes: 13

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215173

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.

Upvotes: 19

brunoais
brunoais

Reputation: 6836

This is my take on this subject.

Advantages to most other examples:

  1. Uses putchar() which is more efficient than printf() or even (although not as much) puts()
  2. Split into two parts (expected to have code inlined) which allows extra efficiency, if wanted.
  3. Is based on very fast RISC arithmetic operations (that includes not using division and multiplication)

Disadvantages to most examples:

  1. Code is not very straightforward.
  2. print_binary_size() modifies the input variable without a copy.

Note: The best outcome for this code relies on using -O1 or higher in gcc or equivalent.

Here's the code:

    inline void print_binary_sized(unsigned int number, unsigned int digits) {
        static char ZERO = '0';
        int digitsLeft = digits;
        
        do{
            putchar(ZERO + ((number >> digitsLeft) & 1));
        }while(digitsLeft--);
    }

    void print_binary(unsigned int number) {
        int digitsLeft = sizeof(number) * 8;
        
        while((~(number >> digitsLeft) & 1) && digitsLeft){
            digitsLeft--;
        }
        print_binary_sized(number, digitsLeft);
    }

Upvotes: 0

danijar
danijar

Reputation: 34175

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

Upvotes: 49

Cosmo Sterin
Cosmo Sterin

Reputation: 171

The combination of functions + macro at the end of this answer can help you.

Use it like that:

float float_var = 9.4;
SHOW_BITS(float_var);

Which will output: Variable 'float_var': 01000001 00010110 01100110 01100110

Note that it is very general and can work with pretty much any type. For instance:

struct {int a; float b; double c;} struct_var = {1,1.1,1.2};
SHOW_BITS(struct_var);

Which will output:

Variable `struct_var`: 00111111 11110011 00110011 00110011 00110011 00110011 00110011 00110011 00111111 10001100 11001100 11001101 00000000 00000000 00000000 00000001

Here's the code:

#define SHOW_BITS(a) ({ \
    printf("Variable `%s`: ", #a);\
    show_bits(&a, sizeof(a));\
})

void show_uchar(unsigned char a)
{
    for(int i = 7; i >= 0; i-= 1) 
        printf("%d", ((a >> i) & 1));
}

void show_bits(void* a, size_t s)
{
    unsigned char* p = (unsigned char*) a;
    for(int i = s-1; i >= 0 ; i -= 1) {
        show_uchar(p[i]);
        printf(" ");
    }
    printf("\n");
}

Upvotes: 1

NoComprende
NoComprende

Reputation: 751

My solution returns an int which can then be used in printf. It can also return the bits in big endian or little endian order.

#include <stdio.h>
#include <stdint.h>

int binary(uint8_t i,int bigEndian)
{
    int j=0,m = bigEndian ? 1 : 10000000;
    while (i)
    {
        j+=m*(i%2);
        if (bigEndian) m*=10; else m/=10;
        i >>= 1;
    }
    return j;
}

int main()
{
    char buf[]="ABCDEF";
    printf("\nbig endian = ");
    for (int i=0; i<5; i++) printf("%08d ",binary(buf[i],1));
    printf("\nwee endian = ");
    for (int i=0; i<5; i++) printf("%08d ",binary(buf[i],0));
    getchar();
    return 0;
}

Outputs

big endian = 01000001 01000010 01000011 01000100 01000101 01000110
wee endian = 10000010 01000010 11000010 00100010 10100010 01100010

Upvotes: 1

jlettvin
jlettvin

Reputation: 1183

// m specifies how many of the low bits are shown.
// Replace m with sizeof(n) below for all bits and
// remove it from the parameter list if you like.

void print_binary(unsigned long n, unsigned long m) {
    static char show[3] = "01";
    unsigned long mask = 1ULL << (m-1);
    while(mask) {
        putchar(show[!!(n&mask)]); mask >>= 1;
    }
    putchar('\n');
}

Upvotes: 0

Robotbugs
Robotbugs

Reputation: 4387

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

Upvotes: 16

Esann
Esann

Reputation: 77

Do a function and call it

display_binary(int n)
{
    long int arr[32];
    int arr_counter=0;
    while(n>=1)
    {
        arr[arr_counter++]=n%2;
        n/=2;
    }
    for(int i=arr_counter-1;i>=0;i--)
    {
        printf("%d",arr[i]);
    }
}

Upvotes: 1

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

}

Upvotes: 5

Rassoul
Rassoul

Reputation: 194

void DisplayBinary(unsigned int n)
{
    int l = sizeof(n) * 8;
    for (int i = l - 1 ; i >= 0; i--) {
        printf("%x", (n & (1 << i)) >> i);
    }
}

Upvotes: 3

Akhil
Akhil

Reputation: 1083

void DisplayBinary(int n)
{
    int arr[8];
    int top =-1;
    while (n)
    {
        if (n & 1)
            arr[++top] = 1;
        else
            arr[++top] = 0;

        n >>= 1;
    }
    for (int i = top ; i > -1;i--)
    {
        printf("%d",arr[i]);
    }
    printf("\n");
}

Upvotes: 1

rakesh jha
rakesh jha

Reputation: 21

#include <stdio.h>
#include <conio.h>

void main()
{
    clrscr();
    printf("Welcome\n\n\n");
    unsigned char x='A';
    char ch_array[8];
    for(int i=0; x!=0; i++)
    {
        ch_array[i] = x & 1;
        x = x >>1;
    }
    for(--i; i>=0; i--)
        printf("%d", ch_array[i]);

    getch();
}

Upvotes: 2

kapil
kapil

Reputation: 624

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

Upvotes: 5

Related Questions