Print an int in binary representation using C
Asked Answered
F

17

24

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.

Fogarty answered 21/6, 2009 at 17:42 Comment(1)
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.Tega
R
36

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);
}
Relict answered 21/6, 2009 at 17:55 Comment(8)
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.Meritocracy
This did the trick, thanks very much! I can get back to this aweful debugging now!Fogarty
You say "assumes little endian", but integer operations are endian-independent.Recoup
You need parentheses in your comparison: ((a & 1) == 0. Otherwise it always prints '1'. I also prefer this: *buffer-- = (a & 1) + '0'Flutist
What does + '0' part do?Austriahungary
@Austriahungary 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.Fieldfare
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 + 1Billbug
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.Chenee
J
10

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;
}
Jaunitajaunt answered 21/6, 2009 at 18:14 Comment(0)
C
8

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);
Corkscrew answered 21/6, 2009 at 17:45 Comment(1)
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.Relict
O
1

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;
        }
    }
Oakland answered 14/5, 2013 at 23:31 Comment(0)
D
1

this is what i made to display an interger as a binairy code it is separated per 4 bits:

int getal = 32;             /** To determain the value of a bit 2^i , intergers are 32bits long**/
int binairy[getal];         /** A interger array to put the bits in **/
int i;                      /** Used in the for loop **/
for(i = 0; i < 32; i++)
{
    binairy[i] = (integer >> (getal - i) - 1) & 1;
}

int a , counter = 0;
for(a = 0;a<32;a++)
{
    if (counter == 4)
    {
        counter = 0;
        printf(" ");
    }
   printf("%i", binairy[a]);
   teller++;
}

it could be a bit big but i always write it in a way (i hope) that everyone can understand what is going on. hope this helped.

Ducky answered 12/1, 2015 at 15:25 Comment(1)
teller in the last line needs to be counter(i transleted it so that everyone can understand)Ducky
E
1
#include<stdio.h>
//#include<conio.h>  // use this if you are running your code in visual c++,      linux don't 
                     // have this library. i have used it for getch() to hold the screen for input char.

void showbits(int);
int main()
{
    int no;
    printf("\nEnter number to convert in binary\n");
    scanf("%d",&no);
    showbits(no);
//  getch();        // used to hold screen... 
                    // keep code as it is if using gcc. if using windows uncomment #include & getch()
    return 0;   

}
void showbits(int n)
{
    int i,k,andmask;

    for(i=15;i>=0;i--)
    {
        andmask = 1 << i;
        k = n & andmask;

        k == 0 ? printf("0") : printf("1");
    }

}
Erenow answered 30/1, 2015 at 3:39 Comment(0)
D
1

Just a enhance of the answer from @Adam Markowitz

To let the function support uint8 uint16 uint32 and uint64:

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

// Convert integer number to binary representation.
// The buffer must have bits bytes length.
void int2bin(uint64_t number, uint8_t *buffer, int bits) {
  memset(buffer, '0', bits);
  buffer += bits - 1;
  for (int i = bits - 1; i >= 0; i--) {
    *buffer-- = (number & 1) + '0';
    number >>= 1;
  }
}

int main(int argc, char *argv[]) {
  char buffer[65];
  buffer[8] = '\0';
  int2bin(1234567890123, buffer, 8);
  printf("1234567890123 in  8 bits: %s\n", buffer);
  buffer[16] = '\0';
  int2bin(1234567890123, buffer, 16);
  printf("1234567890123 in 16 bits: %s\n", buffer);
  buffer[32] = '\0';
  int2bin(1234567890123, buffer, 32);
  printf("1234567890123 in 32 bits: %s\n", buffer);
  buffer[64] = '\0';
  int2bin(1234567890123, buffer, 64);
  printf("1234567890123 in 64 bits: %s\n", buffer);
  return 0;
}

The output:

1234567890123 in  8 bits: 11001011
1234567890123 in 16 bits: 0000010011001011
1234567890123 in 32 bits: 01110001111110110000010011001011
1234567890123 in 64 bits: 0000000000000000000000010001111101110001111110110000010011001011
Doykos answered 21/1, 2022 at 3:17 Comment(0)
C
0

A couple of things:

int f = 32;
int i = 1;
do{
  str[--f] = i^a?'1':'0';
}while(i<<1);
  • It's highly platform dependent, but maybe this idea above gets you started.
  • Why not use memset(str, 0, 33) to set the whole char array to 0?
  • Don't forget to free()!!! the char* array after your function call!
Candra answered 21/6, 2009 at 17:48 Comment(0)
W
0

Two things:

  1. Where do you put the NUL character? I can't see a place where '\0' is set.
  2. Int is signed, and 0xFF000000 would be interpreted as a negative value. So while (a > 0) will be false immediately.

Aside: The malloc function inside is ugly. What about providing a buffer to int2bin?

Watters answered 21/6, 2009 at 17:49 Comment(0)
K
0

Two simple versions coded here (reproduced with mild reformatting).

#include <stdio.h>

/* Print n as a binary number */
void printbitssimple(int n) 
{
    unsigned int i;
    i = 1<<(sizeof(n) * 8 - 1);

    while (i > 0) 
    {
        if (n & i)
            printf("1");
        else
            printf("0");
        i >>= 1;
    }
}

/* Print n as a binary number */
void printbits(int n) 
{
    unsigned int i, step;

    if (0 == n)  /* For simplicity's sake, I treat 0 as a special case*/
    {
        printf("0000");
        return;
    }

    i = 1<<(sizeof(n) * 8 - 1);

    step = -1; /* Only print the relevant digits */
    step >>= 4; /* In groups of 4 */
    while (step >= n) 
    {
        i >>= 4;
        step >>= 4;
    }

    /* At this point, i is the smallest power of two larger or equal to n */
    while (i > 0) 
    {
        if (n & i)
            printf("1");
        else
            printf("0");
        i >>= 1;
    }
}

int main(int argc, char *argv[]) 
{
    int i;
    for (i = 0; i < 32; ++i) 
    {
        printf("%d = ", i);
        //printbitssimple(i);
        printbits(i);
        printf("\n");
    }

    return 0;
}
Kinch answered 21/6, 2009 at 17:57 Comment(0)
A
0
#include <stdio.h>
int main(void) {

    int a,i,k=1;
    int arr[32]; \\ taken an array of size 32

    for(i=0;i <32;i++) 
    {
        arr[i] = 0;   \\initialised array elements to zero
    }

    printf("enter a number\n");
    scanf("%d",&a);  \\get input from the user

    for(i = 0;i < 32 ;i++)
    {
        if(a&k)    \\bit wise and operation
        {
            arr[i]=1;
        }
        else
        {
            arr[i]=0;
        }
        k = k<<1; \\left shift by one place evry time
    }
    for(i = 31 ;i >= 0;i--)
    {
        printf("%d",arr[i]);   \\print the array in reverse
    }

    return 0;
}
Allenaallenby answered 4/12, 2014 at 12:54 Comment(0)
T
0

//This is what i did when our teacher asked us to do this

int main (int argc, char *argv[]) {

    int number, i, size, mask; // our input,the counter,sizeofint,out mask

    size = sizeof(int);
    mask = 1<<(size*8-1);
    printf("Enter integer: ");
    scanf("%d", &number);
    printf("Integer is :\t%d 0x%X\n", number, number);
    printf("Bin format :\t");
    for(i=0 ; i<size*8 ;++i ) {
        if ((i % 4 == 0) && (i != 0))  {
            printf(" ");
        }

        printf("%u",number&mask ? 1 : 0);

        number = number<<1;
    }
    printf("\n");

    return (0);
} 
Terisateriyaki answered 8/1, 2015 at 14:18 Comment(0)
E
0

the simplest way for me doing this (for a 8bit representation):

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

char *intToBinary(int z, int bit_length){

    int div;
    int counter = 0;
    int counter_length = (int)pow(2, bit_length);

    char *bin_str = calloc(bit_length, sizeof(char));

    for (int i=counter_length; i > 1; i=i/2, counter++) {
        div = z % i;
        div = div / (i / 2);
        sprintf(&bin_str[counter], "%i", div);
    }

    return bin_str;
}

int main(int argc, const char * argv[]) {

    for (int i = 0; i < 256; i++) {
        printf("%s\n", intToBinary(i, 8)); //8bit but you could do 16 bit as well
    }

    return 0;
}
Earnest answered 1/12, 2015 at 13:23 Comment(0)
L
0

Here is another solution that does not require a char *.

#include <stdio.h>
#include <stdlib.h>

void    print_int(int i)
{
    int j = -1;
    while (++j < 32)
        putchar(i & (1 << j) ? '1' : '0');
    putchar('\n');
}

int main(void)
{
    int i = -1;
    while (i < 6)
        print_int(i++);
    return (0);
}

Or here for more readability:

#define GRN "\x1B[32;1m"
#define NRM "\x1B[0m"

void    print_int(int i)
{
    int j = -1;
    while (++j < 32)
    {
        if (i & (1 << j))
            printf(GRN "1");
        else
            printf(NRM "0");
    }
    putchar('\n');
}

And here is the output:

11111111111111111111111111111111
00000000000000000000000000000000
10000000000000000000000000000000
01000000000000000000000000000000
11000000000000000000000000000000
00100000000000000000000000000000
10100000000000000000000000000000
Lampion answered 10/12, 2016 at 3:12 Comment(0)
D
0
#include <stdio.h>

#define BITS_SIZE 8

void
int2Bin ( int a )
{
  int i = BITS_SIZE - 1;

   /*
    * Tests each bit and prints; starts with 
    * the MSB
    */
  for ( i; i >= 0; i-- )
  {
    ( a & 1 << i ) ?  printf ( "1" ) : printf ( "0" );
  }
  return;
}

int
main ()
{
  int d = 5;

  printf ( "Decinal: %d\n", d );
  printf ( "Binary: " );
  int2Bin ( d );
  printf ( "\n" );

  return 0;
}
Dimorph answered 1/2, 2017 at 17:52 Comment(0)
P
0

Not so elegant, but accomplishes your goal and it is very easy to understand:

#include<stdio.h>

int binario(int x, int bits)
{
    int matriz[bits];
    int resto=0,i=0;
    float rest =0.0 ;
    for(int i=0;i<8;i++)
    {
        resto = x/2;
        rest = x%2;
        x = resto;
        if (rest>0)
        {
            matriz[i]=1;
        }
        else matriz[i]=0;
    }
    for(int j=bits-1;j>=0;j--)
    {
        printf("%d",matriz[j]);
    }
    printf("\n");
}
int main()
{
    int num,bits;
    bits = 8;
    for (int i = 0; i < 256; i++)
    {
        num = binario(i,bits);
    }
    return 0;
}
Putamen answered 2/7, 2017 at 23:21 Comment(0)
U
-1
void print_binary(int n) {
    if (n == 0 || n ==1) 
        cout << n;
    else {
        print_binary(n >> 1);
        cout << (n & 0x1);
    }
}
Upbraid answered 28/12, 2011 at 22:41 Comment(2)
sorry the 'cout << (n & 0x1)' should also be part of the else part. damn formatting ..Upbraid
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).Foreshore

© 2022 - 2024 — McMap. All rights reserved.