Print an int in binary representation using C

102,220

Solution 1

Here's another option that is more optimized where you pass in your allocated buffer. Make sure it's the correct size.

// buffer must have length >= sizeof(int) + 1
// Write to the buffer backwards so that the binary representation
// is in the correct order i.e.  the LSB is on the far right
// instead of the far left of the printed string
char *int2bin(int a, char *buffer, int buf_size) {
    buffer += (buf_size - 1);

    for (int i = 31; i >= 0; i--) {
        *buffer-- = (a & 1) + '0';

        a >>= 1;
    }

    return buffer;
}

#define BUF_SIZE 33

int main() {
    char buffer[BUF_SIZE];
    buffer[BUF_SIZE - 1] = '\0';

    int2bin(0xFF000000, buffer, BUF_SIZE - 1);

    printf("a = %s", buffer);
}

Solution 2

A few suggestions:

  • null-terminate your string
  • don't use magic numbers
  • check the return value of malloc()
  • don't cast the return value of malloc()
  • use binary operations instead of arithmetic ones as you're interested in the binary representation
  • there's no need for looping twice

Here's the code:

#include <stdlib.h>
#include <limits.h>

char * int2bin(int i)
{
    size_t bits = sizeof(int) * CHAR_BIT;

    char * str = malloc(bits + 1);
    if(!str) return NULL;
    str[bits] = 0;

    // type punning because signed shift is implementation-defined
    unsigned u = *(unsigned *)&i;
    for(; bits--; u >>= 1)
        str[bits] = u & 1 ? '1' : '0';

    return str;
}

Solution 3

Your string isn't null-terminated. Make sure you add a '\0' character at the end of the string; or, you could allocate it with calloc instead of malloc, which will zero the memory that is returned to you.

By the way, there are other problems with this code:

  • As used, it allocates memory when you call it, leaving the caller responsible for free()ing the allocated string. You'll leak memory if you just call it in a printf call.
  • It makes two passes over the number, which is unnecessary. You can do everything in one loop.

Here's an alternative implementation you could use.

#include <stdlib.h>
#include <limits.h>

char *int2bin(unsigned n, char *buf)
{
    #define BITS (sizeof(n) * CHAR_BIT)

    static char static_buf[BITS + 1];
    int i;

    if (buf == NULL)
        buf = static_buf;

    for (i = BITS - 1; i >= 0; --i) {
        buf[i] = (n & 1) ? '1' : '0';
        n >>= 1;
    }

    buf[BITS] = '\0';
    return buf;

    #undef BITS
}

Usage:

printf("%s\n", int2bin(0xFF00000000, NULL));

The second parameter is a pointer to a buffer you want to store the result string in. If you don't have a buffer you can pass NULL and int2bin will write to a static buffer and return that to you. The advantage of this over the original implementation is that the caller doesn't have to worry about free()ing the string that gets returned.

A downside is that there's only one static buffer so subsequent calls will overwrite the results from previous calls. You couldn't save the results from multiple calls for later use. Also, it is not threadsafe, meaning if you call the function this way from different threads they could clobber each other's strings. If that's a possibility you'll need to pass in your own buffer instead of passing NULL, like so:

char str[33];
int2bin(0xDEADBEEF, str);
puts(str);

Solution 4

Here is my solution. It creates a mask, beginning with all 0's and a 1 in the leftmost bit, and logically shifts it right for each bit in the assumed 32-bit integer. The bits are sequentially printed by converting the value of the currently masked integer into a boolean value.

void printBits(int val){
    for(unsigned int mask = 0x80000000; mask; mask >>= 1){
         printf("%d", !!(mask & val));
    }
}

Solution 5

Here is a simple algorithm.

void decimalToBinary (int num) {

        //Initialize mask
        unsigned int mask = 0x80000000;
        size_t bits = sizeof(num) * CHAR_BIT;

        for (int count = 0 ;count < bits; count++) {

            //print
            (mask & num ) ? cout <<"1" : cout <<"0";

            //shift one to the right
            mask = mask >> 1;
        }
    }
Share:
102,220

Related videos on Youtube

gav
Author by

gav

British Software Developer living in Williamsburg, Brooklyn

Updated on July 09, 2022

Comments

  • gav
    gav almost 2 years

    I'm looking for a function to allow me to print the binary representation of an int. What I have so far is;

    char *int2bin(int a)
    {
     char *str,*tmp;
     int cnt = 31;
     str = (char *) malloc(33); /*32 + 1 , because its a 32 bit bin number*/
     tmp = str;
     while ( cnt > -1 ){
          str[cnt]= '0';
          cnt --;
     }
     cnt = 31;
     while (a > 0){
           if (a%2==1){
               str[cnt] = '1';
            }
          cnt--;
            a = a/2 ;
     }
     return tmp;
    
    }
    

    But when I call

    printf("a %s",int2bin(aMask)) // aMask = 0xFF000000
    

    I get output like;

    0000000000000000000000000000000000xtpYy (And a bunch of unknown characters.

    Is it a flaw in the function or am I printing the address of the character array or something? Sorry, I just can't see where I'm going wrong.

    NB The code is from here

    EDIT: It's not homework FYI, I'm trying to debug someone else's image manipulation routines in an unfamiliar language. If however it's been tagged as homework because it's an elementary concept then fair play.

    • Josh The Geek
      Josh The Geek over 9 years
      The random characters are there because this doesn't add a NUL byte at the end of the string. ('\0') This character denotes the end of the string, otherwise printf will keep looking until it finds one, in this case looking through unknown memory.
  • Adam Markowitz
    Adam Markowitz almost 15 years
    Using a static buffer as the return value is not thread safe and also doesn't allow for saving the result for later if multiple calls are involved.
  • user2507101
    user2507101 almost 15 years
    one more code tweak that (IMHO) makes it more readable is to use (a & (1<<i)) instead of (a & 1) followed by (a >>= 1) to verify the i'th bit. That way the loop body contains only the logic, not any statements needed to update values.
  • gav
    gav almost 15 years
    This did the trick, thanks very much! I can get back to this aweful debugging now!
  • Rick Regan
    Rick Regan almost 15 years
    You say "assumes little endian", but integer operations are endian-independent.
  • indiv
    indiv over 14 years
    You need parentheses in your comparison: ((a & 1) == 0. Otherwise it always prints '1'. I also prefer this: *buffer-- = (a & 1) + '0'
  • sean
    sean over 12 years
    sorry the 'cout << (n & 0x1)' should also be part of the else part. damn formatting ..
  • Alexey Frunze
    Alexey Frunze over 12 years
    The question was marked as C, not C++. Also, if n is negative, the result is undefined. Finally, it's not formatting (C/C++ doesn't care about formatting per se), it's the missing parens that must group two statements into one (I've added them for you).
  • JohnMerlino
    JohnMerlino about 10 years
    What does + '0' part do?
  • ramrunner
    ramrunner over 9 years
    @JohnMerlino the (a&1) will check the rightmost byte of a if it is 1. if it is then that operation will return 1. '0' is the ascii code for the letter 0 which is 48 in decimal. '1' is the ascii code for the letter 1 which is 49 in decimal. so this addition when the rightmost bit is 0 will eval to 48 which prints 0 while when it is 1 it will eval to 49 which prints 1.
  • Kirito
    Kirito over 9 years
    teller in the last line needs to be counter(i transleted it so that everyone can understand)
  • levengli
    levengli over 8 years
    BUF_SIZE is set to 33, but this based on the assumption that sizeof(int) equal 4. Since this is not necessarily the case, a more accurate definition would be: sizeof(int) * 8 + 1
  • rbaleksandar
    rbaleksandar about 7 years
    I would suggest binding the for loop's starting value to the buf_size like this: for (i = buf_size-2; i >= 0; i--) { ... }. Otherwise the code is unusable if BUF_SIZE is set to anything other than 33.