Bit shifting results in negative number - c

I'm working on an assignment that deals with compression and decompression. More specifically, a variation of run-length encoding (9-bit blocks). The issue I am having deals with the sign of the "type" bit. I am able to acquire the desired bit, however, in the cases that the bit should be a 1, my printf returns -1. This would lead me to believe that I am not doing something correct in my bit shifting, but I am unaware as to what that might be.
void bitShift(char * mostFreq, unsigned char * byteBuf, int byteCount) {
char type;
int typels = 0;
int typers = 7;
int i = 0;
for(i = 0; i < byteCount - 1; i++) {
type = byteBuf[i];
printf("type before = %d\t", (unsigned int)type);
type = type << typels;
type = type >> typers;
typels++;
printf("type after = %d\n", (unsigned int)type);
}/*End for i*/
for(i = 0; i < byteCount; i++)
byteBuf[i] = 0;
}/*End bitShift*/
void decompressFile(char * mostFreq) {
unsigned char byteBuf[9] = { 0 };
int num, byteCount, i;
num = 0; byteCount = 0; i = 0;
unsigned char buf;
while((num = read(0,&buf, 1)) > 0) {
byteBuf[byteCount] = buf;
byteCount++;
if(byteCount == 9) {/*Flush bytes if buffer is full*/
bitShift(mostFreq, byteBuf, byteCount);
for(i = 0; i < 9; i++) {
byteBuf[i] = 0;
}/*End for i*/
byteCount = 0;
}/*End if*/
}/*End while*/
if(num == 0) {/*If EOF*/
if(byteCount != 0) {/*Bits have not been flushed*/
bitShift(mostFreq, byteBuf, byteCount);
}/*End if*/
} else if(num < 0) {
perror("Read error");
exit(1);
}/*End else if*/
}/*End decompressFile*/

You problem is that you declared type as a plain char that, in your system seems to be a signed type.
So when you have for example 0x80, it is actually -128, a negative number, and when it is shifted to the right the sign bit is extended: 1 bit: 0xC0 (-64), 2 bits: 0xE0 (-32), ... 7 bits: 0xFF (-1).
Change it to unsigned char and done!

Related

Why does the array keep reverting to 0

I have a 1 dimensional array in which ive initialized as 0 but for some reason when i go inside a loop and try to increase its contents by one the value at position 0 keeps reverting to 0 even after i increase it by 1.
#include <stdio.h>
#include <stdlib.h>
#define TOTAL_V 3
#define NUM_CANDIDATES 7
int hex_age(unsigned short hex){
unsigned short age = hex >> 9;
if (age >18 && age <101)
return age;
else return 0;
}
int hex_gender(unsigned short hex){
unsigned short gender = hex >> 7 & 3;
return gender;
}
int hex_vote(unsigned short hex){
unsigned short vote, tmp = hex & 0x7f , count = 0;
if (tmp == 0)
return 7;
for (int i = 0 ; i<7; i++){
if (tmp & 1 == 1){
count++;
vote = i;
}
tmp = tmp >> 1;
}
if (count > 1)
return 7;
return vote;
}
int main() {
int s_votes = 0, f_votes = 0, v_count[NUM_CANDIDATES] = {0};
unsigned short **v_info, hex_v_info , age , gender , vote;
FILE *fp;
fp = fopen("data1.dat" , "r");
if (fp == NULL){
fprintf(stderr ,"apotuxe o anoigmos tou arxeiou");
exit(-1);
}
if (feof(fp)){
fprintf(stderr, "to arxeio einai adeio");
exit(-1);
}
while (fscanf(fp ,"%x", &hex_v_info) != EOF){
age = hex_age(hex_v_info);
if(age == 0)
f_votes++;
else {
gender = hex_gender(hex_v_info);
if (gender == 0)
f_votes++;
else{
vote = hex_vote(hex_v_info);
if (vote == 7)
f_votes++;
else{
if (s_votes == 0){
v_info = malloc(sizeof(int *));
v_info[s_votes] =malloc(sizeof(int)* TOTAL_V);
}
else{
v_info = realloc(v_info , sizeof(int *)*(s_votes+1));
v_info[s_votes] = malloc(sizeof(int)*TOTAL_V);
}
v_info[s_votes][0] = age;
v_info[s_votes][1] = gender;
v_info[s_votes][2] = vote;
v_count[vote]++;
s_votes++;
}
}
}
}
fclose(fp);
for (int i = 0; i<s_votes; i++)
free(v_info);
return 0;
}
and for some reason when i use calloc to create the array it doesnt have that problem. Does anyone know why that happens
You declare unsigned short hex_v_info (2 bytes on my system), then read data from with fscanf(fp ,"%x", &hex_v_info) where the format string %x expect the address of an int (4 bytes on my system). This will certainly overwrite data unexpectedly.
unsigned short **v_info but you store an array of int [s_votes]. If your pointers are not uniform this will be a problem.
realloc(NULL, 1) is well defined so just use instead of malloc() of the first element. You need to assign the result of realloc()` to e temporary variable, however, to be able handle NULL. Otherwise you lose data & leak memory.
free(v_info); results in a double free if s_votes > 1, and you still leak the memory you allocate at v_info[i].
#include <stdio.h>
#include <stdlib.h>
#define TOTAL_V 3
#define NUM_CANDIDATES 7
// 0x1111 1110 0000 0000
int hex_age(unsigned short hex){
unsigned short age = hex >> 9;
if (age >18 && age < 101)
return age;
return 0;
}
// 0x0000 0001 1000 0000
int hex_gender(unsigned short hex){
unsigned short gender = hex >> 7 & 3; // bit 7 and 6
return gender;
}
// 0x0000 0000 0111 1111
int hex_vote(unsigned short hex){
unsigned short vote, tmp = hex & 0x7f , count = 0; // bit 11 through 0
if (tmp == 0)
return 7;
for (int i = 0 ; i<7; i++){
if ((tmp & 1) == 1){
count++;
vote = i;
}
tmp = tmp >> 1;
}
if (count > 1)
return 7;
return vote;
}
int main() {
int s_votes = 0, f_votes = 0, v_count[NUM_CANDIDATES] = {0};
unsigned short hex_v_info;
int **v_info = NULL;
FILE *fp = fopen("data1.dat" , "r");
if (!fp){
fprintf(stderr ,"apotuxe o anoigmos tou arxeiou");
exit(-1);
}
for(;;) {
int rv = fscanf(fp ,"%hx", &hex_v_info);
if(rv == EOF) break;
if(rv != 1) {
printf("err\n");
return 1;
}
unsigned short age = hex_age(hex_v_info);
if(!age) {
f_votes++;
continue;
}
unsigned short gender = hex_gender(hex_v_info);
if (!gender) {
f_votes++;
continue;
}
unsigned short vote = hex_vote(hex_v_info);
if (vote == 7) {
f_votes++;
continue;
}
int **tmp = realloc(v_info, sizeof *tmp * (s_votes + 1));
if(!tmp) {
// handle error: free v_info[i] and v_info?
return 1;
}
v_info = tmp;
v_info[s_votes] = malloc(sizeof **v_info * TOTAL_V);
v_info[s_votes][0] = age;
v_info[s_votes][1] = gender;
v_info[s_votes][2] = vote;
v_count[vote]++;
s_votes++;
}
fclose(fp);
printf("f_votes: %d\n", f_votes);
for(size_t i = 0; i < s_votes; i++) {
printf("%zu: %d %d %d\n",
i,
v_info[i][0],
v_info[i][1],
v_info[i][2]
);
}
for (int i = 0; i< s_votes; i++)
free(v_info[i]);
free(v_info);
return 0;
}
and with input file file:
a081
a082
it appears to process the info data correctly:
f_votes: 0
0: 80 1 0
1: 80 1 1

why the last number in doted decimal is not converted to binary?

#include<stdio.h>
#include<string.h>
#include <math.h>
long long convertDecimalToBinary(int n);
int main() {
int verify;
long long bip, dip;
char str1[100];
printf("Enter dotted decimal ip address :\n");
scanf("%s",str1);
verify = bin_verify(str1);
seperate(str1);
return 0;
}
int bin_verify(char str1[]) {
int i;
for(i = 0; i < strlen(str1); i++) {
if((str1[i] < 255) && (str1[i] > 0)) {
return 1;
}
}
}
// function to get first decimal no sepreted
int seperate(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s1 = atoi(a);
s1 = convertDecimalToBinary(s1);
printf("Binary Format of IP :\n");
printf("%d.",s1);
seperate2(str1);
return 0;
}
// function to get second decimal no sepreted
int seperate2(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s2 = atoi(a);
s2 = convertDecimalToBinary(s2);
printf("%d.",s2);
seperate3(str1);
return 0;
}
// function to get third decimal no sepreted
int seperate3(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s3 = atoi(a);
s3 = convertDecimalToBinary(s3);
printf("%d.",s3);
seperate4(str1);
return 0;
}
// function to get fourth decimal no sepreted
int seperate4(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s4 = atoi(a);
s4 = convertDecimalToBinary(s4);
printf("%d\n",s4);
return 0;
}
//to convert decimal to binary
long long convertDecimalToBinary(int n)
{
//printf("%d", n);
long long binaryNumber = 0;
int remainder, i = 1,step=0;
while (n!=0)
{
remainder = n%2;
// printf("Step %d: %d/2, Remainder = %d, Quotient = %d\n", step++, n, remainder, n/2);
n /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
output:
Enter dotted decimal ip address :
192.15.7.4
Binary Format of IP :
11000000.1111.111.0
I want to convert ip address to binary but,
It always return 0 as binary of last decimal number.
why it is not performing seperate4() function?
What you have done wrong is already listed in the comments but you are doing it overly complicated, nearly Rube-Goldberg like. It is quite simple and can be done without any complicated tricks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
char *int8_to_bin(int n, char *buf)
{
int i = 8;
// we need an unsigned integer for the bit-juggling
// because of two's complement numbers.
// Not really needed here because the input is positive
unsigned int N;
// check for proper size
if (n < 0 || n > 255) {
return NULL;
}
// is safe now
N = (unsigned int) n;
// we work backwards here, least significant bit first
// but we want it least significant bit last.
while (i--) {
// make a (character) digit out of an integer
buf[i] = (char) (N & 0x1) + '0';
// shift one bit to the right and
// drop the least significant bit by doing it
N >>= 1;
}
// return the pointer to the buffer we got (for easier use)
return buf;
}
int main(int argc, char **argv)
{
// keeps the intermediate integer
int addr;
// command-line argument, helper for strtol() and int8_to_bin()
char *s, *endptr, *cp;
// buffer for int8_to_bin() to work with
// initialize to all '\0';
char buf[9] = { '\0' };
// array holding the end-result
// four 8-character groups with three periods and one NUL
char binaddr[4 * 8 + 3 + 1];
// iterator
int i;
if (argc < 2) {
fprintf(stderr, "Usage: %s dotted_ipv4\n", argv[0]);
exit(EXIT_FAILURE);
}
// set a pointer pointing to the first argument as a shortcut
s = argv[1];
// the following can be done in a single loop, of course
// strtol() skips leading spaces and parses up to the first non-digit.
// endptr points to that point in the input where strtol() decided
// it to be the first non-digit
addr = (int) strtol(s, &endptr, 0);
// work on copy to check for NULL while keeping the content of buf
// (checking not done here)
cp = int8_to_bin(addr, buf);
// if(cp == NULL)...
// copy the result to the result-array
// cp has a NUL, is a proper C-string
strcpy(binaddr, cp);
// rinse and repeat three times
for (i = 1; i < 4; i++) {
// skip anything between number and period,
// (or use strchr() to do so)
while (*endptr != '.'){
endptr++;
}
// skip the period itself
endptr++;
// add a period to the output
strcat(binaddr, ".");
// get next number
addr = (int) strtol(endptr, &endptr, 0);
cp = int8_to_bin(addr, buf);
// if(cp == NULL)...
strcat(binaddr, cp);
}
printf("INPUT: %s\n", s);
printf("OUTPUT: %s\n", binaddr);
exit(EXIT_SUCCESS);
}
We don't need a complicated parsing algorithm, strtol() does it for us, we just need to find the next period ourselves. The size of all in- and output is known and/or can be easily checked if they are inside their limits--e.g.: no need for tedious and error-prone memory allocations, we can use fixed size buffers and strcat().
There is a principle, that holds not only in the Navy but also in programming: KISS.

How to convert ascii string to binary?

I'm trying to convert an ascii string to a binary string in C. I found this example Converting Ascii to binary in C but I rather not use a recursive function. I tried to write an iterative function as opposed to a recursive function, but the binary string is missing the leading digit. I'm using itoa to convert the string, however itoa is a non standard function so I used the implementation from What is the proper way of implementing a good "itoa()" function? , the one provided by Minh Nguyen.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int32_t ascii_to_binary(char *input, char **out, uint64_t len)
{
uint32_t i;
uint32_t str_len = len * 8;
if(len == 0)
{
printf("Length argument is zero\n");
return (-1);
}
(*out) = malloc(str_len + 1);
if((*out) == NULL)
{
printf("Can't allocate binary string: %s\n", strerror(errno));
return (-1);
}
if(memset((*out), 0, (str_len)) == NULL)
{
printf("Can't initialize memory to zero: %s\n", strerror(errno));
return (-1);
}
for(i = 0; i < len; i++)
itoa((int32_t)input[i], &(*out)[(i * 8)], 2);
(*out)[str_len] = '\0';
return (str_len);
}
int main(void)
{
int32_t rtrn = 0;
char *buffer = NULL;
rtrn = ascii_to_binary("a", &buffer, 1);
if(rtrn < 0)
{
printf("Can't convert string\n");
return (-1);
}
printf("str: %s\n", buffer);
return (0);
}
I get 1100001 for ascii character a, but I should get 01100001, so how do I convert the ascii string to the whole binary string?
You could change the for loop to something like this:
for(i = 0; i < len; i++) {
unsigned char ch = input[i];
char *o = *out + 8 * i;
int b;
for (b = 7; b >= 0; b--)
*o++ = (ch & (1 << b)) ? '1' : '0';
}
or similar:
for(i = 0; i < len; i++) {
unsigned char ch = input[i];
char *o = &(*out)[8 * i];
unsigned char b;
for (b = 0x80; b; b >>= 1)
*o++ = ch & b ? '1' : '0';
}
This program gets and integer ( which contains 32 bits ) and converts it to binary, Work on it to get it work for ascii strings :
#include <stdio.h>
int main()
{
int n, c, k;
printf("Enter an integer in decimal number system\n");
scanf("%d", &n);
printf("%d in binary number system is:\n", n);
for (c = 31; c >= 0; c--)
{
k = n >> c;
if (k & 1)
printf("1");
else
printf("0");
}
printf("\n");
return 0;
}
Best just write a simple function to do this using bitwise operators...
#define ON_BIT = 0x01
char *strToBin(char c) {
static char strOutput[10];
int bit;
/*Shifting bits to the right, but don't want the output to be in reverse
* so indexing bytes with this...
*/
int byte;
/* Add a nul at byte 9 to terminate. */
strOutput[8] = '\0';
for (bit = 0, byte = 7; bit < 8; bit++, byte--) {
/* Shifting the bits in c to the right, each time and'ing it with
* 0x01 (00000001).
*/
if ((c >> bit) & BIT_ON)
/* We know this is a 1. */
strOutput[byte] = '1';
else
strOutput[byte] = '0';
}
return strOutput;
}
Something like that should work, there's loads of ways you can do it. Hope this helps.

How to get and set bits for bits in char string?

Usually bit operations are done in smaller data width such as int, unsigned int or wchar_t. Assuming we want to use the bit strings in a longer format, how to shift, get and set bits for bits in char string?
One way may be to divide and conquer using the conventional method, but how do we ensure the bit carry over?
Given
#define numberOfState 2000 // number of bits
#define numberOfBitsIn1Byte 8
char* record;
int numberOfCharRequiredToRepresentBits =
ceil(((float)numberOfState/(float)numberOfBitsIn1Byte));
record = (char*) malloc(sizeof(char)*numberOfCharRequiredToRepresentBits);
// record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
// optional : initialization by doing the set bit according to
// input from files. After which, do free(record);
How may we conduct bit operations such as to
i. shift the *record
ii. get bits from a specific bit position in *record
iii. set bits from a specific bit position in *record
Please have a try with following code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isLittleEndian = 1;
void checkEndian(void)
{
union
{
short inum;
char c[sizeof(short)];
} un;
un.inum=0x0102;
if(un.c[0]==1 && un.c[1]==2)
{
printf("big_endian.\n");
isLittleEndian = 0;
}
else if(un.c[0]==2 && un.c[1]==1)
{
printf("little_endian.\n");
isLittleEndian = 1;
}
}
void shift_L(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst, src + shiftBytes, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = 0; i < len; i++)
{
if (isLittleEndian)
{
tmp = *(dst+i) << 8 | *(dst+i+1);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp + 1);
}
else
{
tmp = *(short *)(dst+i);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp);
}
}
}
}
void shift_R(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst + shiftBytes, src, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = len -1; i >= 0; i--)
{
if (isLittleEndian)
{
tmp = *(dst+i-1) << 8 | *(dst+i);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp);
}
else
{
tmp = *(short *)(dst+i-1);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp+1);
}
}
}
}
int getBit(char *src, int n)
{
unsigned char tmp = *(src + n/8);
unsigned char mask = (0x1 << (8 - n%8 - 1));
int bit = 0;
bit = (tmp & mask) > 0;
printf("%d", bit);
}
void setBit(char *src, int n, int bit)
{
unsigned char * pTmp = src + n/8;
unsigned char mask = (0x1 << (8 - n%8 - 1));
if (bit)
{
*pTmp |= mask;
}
else
{
*pTmp &= ~mask;
}
}
void dumpBin(unsigned char *src, int len)
{
int i = 0;
int j = 0;
unsigned char mask = 0;
for ( i = 0; i < len; i++)
{
for ( j = 0; j < 8; j++)
{
mask = 0x1 << 8 - j - 1;
printf("%d",(*(src + i) & mask) > 0);
}
}
}
void main()
{
char *record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
//char *record = "NAXHDKA";
int recordLen = strlen(record);
char * buffer = NULL;
int i = 0;
checkEndian();
recordLen = recordLen + recordLen%2;
buffer = malloc(recordLen);
memcpy(buffer, record, recordLen);
printf("\n input bit stream:\n");
dumpBin(buffer, recordLen);
printf("\n bit stream from getBit:\n");
for ( i = 0; i < recordLen*8; i++)
{
getBit(buffer, i);
}
setBit(buffer, 8, 1);
setBit(buffer, 9, 0);
setBit(buffer, 10, 1);
setBit(buffer, 11, 1);
printf("\n bit stream after setBit:\n");
dumpBin(buffer, recordLen);
shift_L(record, buffer, recordLen, 1);
printf("\n bit stream after shift_L:\n");
dumpBin(buffer, recordLen);
shift_R(record, buffer, recordLen, 9);
printf("\n bit stream after shift_R:\n");
dumpBin(buffer, recordLen);
printf("\n");
free(buffer);
}
Your bitstream is essentially an array of char. So, to perform these operations you work on these char elements.
i. The shifting operation depends on the number of bits you want to shift.
If the number is a multiple of 8, it is pretty straightforward, you just copy the elements right of left as many bytes as the number is a multiple of 8.
If the number is less than 8, you perform the operation on every element of the array, but you need to or the overflowing bits of the previous element. For example, in left shift, element i must incorporate the overflowing bits of element i+1, and on right shift, the overflowing bits of element i-1.
Any other number of bits you want to shift can be achieved by a combination of these two actions. For example, a left shift by 18 is a shift by 16 followed by a shift by 2.
In any case, you need to be careful on which side of the bitstring you start, so that you do not lose data.
ii. In order to get the n-th bit of the bitstream, you access the element with index n/8 (integer division) and get the n%8 bit from it.
iii. Pretty much the same as ii.

Print an int in binary representation using C

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.
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);
}
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;
}
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);
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;
}
}
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.
#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");
}
}
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
Two things:
Where do you put the NUL character? I can't see a place where '\0' is set.
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?
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!
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;
}
//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);
}
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;
}
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
#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;
}
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;
}
#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;
}
void print_binary(int n) {
if (n == 0 || n ==1)
cout << n;
else {
print_binary(n >> 1);
cout << (n & 0x1);
}
}

Resources