Print an int in binary representation using C
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 aprintf
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;
}
}
Related videos on Youtube
Comments
-
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 over 9 yearsThe 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 almost 15 yearsUsing 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 almost 15 yearsone 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 almost 15 yearsThis did the trick, thanks very much! I can get back to this aweful debugging now!
-
Rick Regan almost 15 yearsYou say "assumes little endian", but integer operations are endian-independent.
-
indiv over 14 yearsYou need parentheses in your comparison: ((a & 1) == 0. Otherwise it always prints '1'. I also prefer this: *buffer-- = (a & 1) + '0'
-
sean over 12 yearssorry the 'cout << (n & 0x1)' should also be part of the else part. damn formatting ..
-
Alexey Frunze over 12 yearsThe 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 about 10 yearsWhat does + '0' part do?
-
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 over 9 yearsteller in the last line needs to be counter(i transleted it so that everyone can understand)
-
levengli over 8 years
BUF_SIZE
is set to 33, but this based on the assumption thatsizeof(int)
equal 4. Since this is not necessarily the case, a more accurate definition would be:sizeof(int) * 8 + 1
-
rbaleksandar about 7 yearsI would suggest binding the
for
loop's starting value to thebuf_size
like this:for (i = buf_size-2; i >= 0; i--) { ... }
. Otherwise the code is unusable ifBUF_SIZE
is set to anything other than33
.