Display the binary representation of a number in C?

113,745

Solution 1

Yes (write your own), something like the following complete function.

#include <stdio.h> /* only needed for the printf() in main(). */
#include <string.h>

/* Create a string of binary digits based on the input value.
   Input:
       val:  value to convert.
       buff: buffer to write to must be >= sz+1 chars.
       sz:   size of buffer.
   Returns address of string or NULL if not enough space provided.
*/
static char *binrep (unsigned int val, char *buff, int sz) {
    char *pbuff = buff;

    /* Must be able to store one character at least. */
    if (sz < 1) return NULL;

    /* Special case for zero to ensure some output. */
    if (val == 0) {
        *pbuff++ = '0';
        *pbuff = '\0';
        return buff;
    }

    /* Work from the end of the buffer back. */
    pbuff += sz;
    *pbuff-- = '\0';

    /* For each bit (going backwards) store character. */
    while (val != 0) {
        if (sz-- == 0) return NULL;
        *pbuff-- = ((val & 1) == 1) ? '1' : '0';

        /* Get next bit. */
        val >>= 1;
    }
    return pbuff+1;
}

Add this main to the end of it to see it in operation:

#define SZ 32
int main(int argc, char *argv[]) {
    int i;
    int n;
    char buff[SZ+1];

    /* Process all arguments, outputting their binary. */
    for (i = 1; i < argc; i++) {
        n = atoi (argv[i]);
        printf("[%3d] %9d -> %s (from '%s')\n", i, n,
            binrep(n,buff,SZ), argv[i]);
    }

    return 0;
}

Run it with "progname 0 7 12 52 123" to get:

[  1]         0 -> 0 (from '0')
[  2]         7 -> 111 (from '7')
[  3]        12 -> 1100 (from '12')
[  4]        52 -> 110100 (from '52')
[  5]       123 -> 1111011 (from '123')

Solution 2

There is no direct way (i.e. using printf or another standard library function) to print it. You will have to write your own function.

/* This code has an obvious bug and another non-obvious one :) */
void printbits(unsigned char v) {
   for (; v; v >>= 1) putchar('0' + (v & 1));
}

If you're using terminal, you can use control codes to print out bytes in natural order:

void printbits(unsigned char v) {
    printf("%*s", (int)ceil(log2(v)) + 1, ""); 
    for (; v; v >>= 1) printf("\x1b[2D%c",'0' + (v & 1));
}

Solution 3

Based on dirkgently's answer, but fixing his two bugs, and always printing a fixed number of digits:

void printbits(unsigned char v) {
  int i; // for C89 compatability
  for(i = 7; i >= 0; i--) putchar('0' + ((v >> i) & 1));
}

Solution 4

#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
void displayBinary(int n)
{
       char bistr[1000];
       itoa(n,bistr,2);       //2 means binary u can convert n upto base 36
       printf("%s",bistr);

}

int main()
{
    int n;
    cin>>n;
    displayBinary(n);
    getch();
    return 0;
}

Solution 5

Use a lookup table, like:

char *table[16] = {"0000", "0001", .... "1111"};

then print each nibble like this

printf("%s%s", table[a / 0x10], table[a % 0x10]);

Surely you can use just one table, but it will be marginally faster and too big.

Share:
113,745
Paul Wicks
Author by

Paul Wicks

Updated on July 18, 2022

Comments

  • Paul Wicks
    Paul Wicks almost 2 years

    Possible Duplicate:
    Is there a printf converter to print in binary format?

    Still learning C and I was wondering:

    Given a number, is it possible to do something like the following?

    char a = 5;
    printf("binary representation of a = %b",a);
    > 101
    

    Or would i have to write my own method to do the transformation to binary?

  • visual_learner
    visual_learner about 15 years
    Nice bit hacks. Unreadable code FTW!
  • dirkgently
    dirkgently about 15 years
    @Chris Lutz: Actually, this is as simple as they come :-)
  • abelenky
    abelenky about 15 years
    @Chris Lutz: I agree with dirkgently. The function is well named, and clearly written in a linear fashion. Each statement is simple and obvious.
  • paxdiablo
    paxdiablo about 15 years
    Yeah, not sure I'd be inflicting this monstrosity :-) on someone "Still learning C". Still, it works.
  • visual_learner
    visual_learner about 15 years
    I upvoted, and actually do like the solution. I just am also a bit sarcastic sometimes. Sorry it seemed like I thought it was bad. I think it's quite readable, if you know bitwise operations. Which a lot of people unfortunately don't. (Also, the >>= and <<= operators just look a bit silly to me.)
  • Kevin Lacquement
    Kevin Lacquement about 15 years
    You missed the case where the input is 0, which will print nothing in this case.
  • dirkgently
    dirkgently about 15 years
    @Pax: Do you equate terseness with monstrosity? Alas, any student of C has to live with such monstrosity, for that is the C way of life. The earlier they learn, the better it is.
  • dirkgently
    dirkgently about 15 years
    @Chris Lutz: +2; It was the other way round for me though :)
  • unwind
    unwind about 15 years
    Very confusing to show a string function in C that takes a buffer size as input, and doesn't use that size in a defensive (enough) manner. For sz == 0 && x == 0, it will still write "0" to the buffer.
  • Jonathan Leffler
    Jonathan Leffler about 15 years
    The other bug is that it only prints out for a byte at a time, not for 32-bit or 64-bit values. Though, since the question was about printing a 'char', maybe that doesn't matter.
  • dirkgently
    dirkgently about 15 years
    @unwind: Which buffer size parameter are you talking about?
  • Jonathan Leffler
    Jonathan Leffler about 15 years
    I see a buffer underflow if the binrep() function is not given enough space for the value it is printing. And, speaking from bitter (but long ago) experience, stuff writing off the front of an array can be really nasty to debug!
  • paxdiablo
    paxdiablo about 15 years
    Yes, that will be troublesome - if your ints are more than 32 bits, you have to make sure you increase SZ to suit.
  • paxdiablo
    paxdiablo about 15 years
    @dirk, I gather that buffer size comment was meant for my answer.
  • Leon
    Leon about 15 years
    As icing on the cake you could also replace i = 7 with (sizeof(v)*8)-1
  • dirkgently
    dirkgently about 15 years
    @Pax: Oh, well, so I gathered :-) Just wanted a confirmation from unwind.
  • paxdiablo
    paxdiablo about 15 years
    Fixed to prevent the buffer overflow.
  • paxdiablo
    paxdiablo about 15 years
    Quote: "buff: buffer to write to must be >= sz+1 chars." - sz is the size of the buffer, excluding the terminating null.
  • unwind
    unwind about 15 years
    @Pax: Oh, okay ... I'll delete my comment. I get queasy when exposed to a function taking a string size argument that is incompatible with a simple sizeof; requiring me to remember to add or subtract 1 is not cool, in my opinion.
  • paxdiablo
    paxdiablo about 15 years
    Well, it has precedent, in fgets(), so I guess it's not a total anti-pattern.
  • visual_learner
    visual_learner about 15 years
    I'd do that if I could find a way to make the function take an argument of any type, rather than just an unsigned char. I tried using a void pointer, but I'm getting errors. I'll need to look into that more sometime though.
  • David Xia
    David Xia over 12 years
    this worked for me:char* printbits(int v) { for(int i = (sizeof(v)*8)-1; i >= 0; i--) putchar('0' + ((v >> i) & 1)); }
  • David Xia
    David Xia over 12 years
    Is there a way to have it return char*?
  • visual_learner
    visual_learner over 12 years
    @David - Of course there is. Google around for other questions related to this. (Or ask your own, but I bet it's a duplicate.) You'll probably need to use malloc.
  • David 天宇 Wong
    David 天宇 Wong over 10 years
    I still don't understand this "for"
  • dotancohen
    dotancohen about 9 years
    I will start adding that comment to some methods of mine that I know that I have not properly debugged. For myself it will be a reminder. For others, it will be a warning.
  • DanSkeel
    DanSkeel about 9 years
    Also consider i = v ? (int)floor(log2(v)) : 0