3

I am very new to the C language. I will need a small program to convert int to binary and the binary preferably stored in an array so that I can further break them apart for decoding purpose. I have following:

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

int main()
{
    int arr[20];
    int dec = 40;
    int i = 0, ArrLen;

    if(dec > 0)
    {
        while(dec > 0)
        {
            arr[i] = dec % 2;
            i++;
            dec = dec / 2;
        }
    }
    else
    {
        printf("Invalid Number");
    }
}

From the code above, I can store the binary value in arr. But instead of getting the binary equivalent: 101000, the array now is like {0, 0, 0, 1, 0, 1}, which is the reversed of the correct answer. So the question is, how to get an array in the correct order or possibly flip it? I have one thing for sure, and that is the maximum array length will not exceed 8 elements.

This conversion will be used repeatedly. So I plan to put it in a function so I'd be able to call the function, pass in an integer, and then get the array as the return value. So another question is, is it feasible to get an array as the return value?

Student
  • 805
  • 1
  • 8
  • 11
Fei Hap Lee
  • 201
  • 1
  • 7
  • 17
  • Start with thinking about how you would do this by hand. Then put that into code. The value in an int is already binary by the way. There are many different ways to do this, especially if you levy what you know about how computers store data. But I'm guessing this is assignment for a class since this is something that most schools have you do early. – ydobonebi Jul 23 '15 at 04:00
  • HI Quinn, this is not an assignment anyway. I am far after school. Just I am actually doing more on C#, PHP & JAVA. Not any C language.Printing out as an BINARY is easy from an int, but to store them, I can't catch any ball yet. – Fei Hap Lee Jul 23 '15 at 04:02
  • You can't pass an array in C. You have to `malloc` in the function and return a pointer to the address. – M. Shaw Jul 23 '15 at 04:04
  • http://ideone.com/Woyw8H – Kaustav Ray Jul 23 '15 at 04:12
  • 1
    @M.Shaw `struct R { unsigned char ar[8]; }; struct R func(int value) { struct R r; .... return r; }` - If you bury a fixed array in a `struct`, you *can* return it by-value. The compiler will generate the appropriate code to do it if asked. Whether that is needed, or desirable, for this task is a different issue. – WhozCraig Jul 23 '15 at 05:54

8 Answers8

8

You can parameterize the array by using a pointer to int. It may be useful to parameterize the number of digits as well.

void int_to_bin_digit(unsigned int in, int count, int* out)
{
    /* assert: count <= sizeof(int)*CHAR_BIT */
    unsigned int mask = 1U << (count-1);
    int i;
    for (i = 0; i < count; i++) {
        out[i] = (in & mask) ? 1 : 0;
        in <<= 1;
    }
}

int main(int argc, char* argv[])
{
    int digit[8];
    int_to_bin_digit(40, 8, digit);
    return 0;
}
Johnny Cage
  • 528
  • 2
  • 6
  • Minor: /* assert: count <= sizeof(unsigned)*CHAR_BIT && count > 0 */ – chux - Reinstate Monica Jul 23 '15 at 11:50
  • @chux I was on the fence about `sizeof(?)`, since it's evaluating a signed type and only casting to unsigned to use a logical shift. A `count` of zero shouldn't be flagged as an error, but less than zero is probably a mistake. In practice `count` should be unsigned. – Johnny Cage Jul 25 '15 at 11:19
  • Asserting `count>0` helps with as `count == 0` is a problem with `1U << (count-1);`. Note `count` is not cast to unsigned in ` 1U << (count-1)`. – chux - Reinstate Monica Jul 27 '15 at 01:55
2

or recursive V2.0:

#include <stdio.h>

char *binaryToAbits(unsigned int answer, char *result) {
  if(answer==0) return result;
  else {
    result=binaryToAbits(answer>>1,result);
    *result='0'+(answer & 0x01);
    return result+1;
  }
}

int main(void) {
    unsigned int numToConvert=0x1234ABCD;
    char ascResult[64];
    *binaryToAbits(numToConvert,ascResult)='\0';
    printf("%s",ascResult);
    return 0;
}

Note, thanks to @chux, here is a better recursive function that handles the case of converting 0 - it outputs "0" instead of "":

char *binaryToAbits(unsigned int answer, char *result) {
  if(answer>1) {
    result=binaryToAbits(answer>>1,result);
  }
  *result='0'+(answer & 0x01);
  return result+1;
};
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
Martin James
  • 24,453
  • 3
  • 36
  • 60
  • 1
    1) `numToConvert=0` --> `""` rather than `"0"`. 2) Certainly 64 enough for `0x1234ABCD`, but I'd expect 65 or 33. – chux - Reinstate Monica Jul 23 '15 at 11:39
  • @chux - sure, but that would require another function to check for 0. Easy enough, I just didn't bother with it. Buffer size: I thought 32, then 33 for the nul, then rounded up to 64:) – Martin James Jul 23 '15 at 12:15
  • 1
    "require another function to check for 0". Hmmm, maybe a small re-write instead: `if (answer > 1) {result=binaryToAbits(answer>>1,result); } *result='0'+(answer & 1); return result+1;` Somewhat simple and yet handles `0` well. – chux - Reinstate Monica Jul 23 '15 at 12:35
  • @chux good idea! With your permission, I would edit it in and add an attribution. – Martin James Jul 23 '15 at 14:37
  • In fact, sod it, I'm gonna add it anyway. If you object, I'll remove it, or you can:) – Martin James Jul 23 '15 at 14:42
2

Same answer as Johnny Cage with the addtion of a function to get the length of a digit

#include <math.h>

int bit_len(unsigned int n){
   return floor(log(n)/log(2))+1;
}
void int_to_bin_digit(unsigned int in, int len_digitis,int* out_digit){

  unsigned int mask = 1U << (len_digitis-1);
  int i;
  for (i = 0; i < len_digitis; i++) {
    out_digit[i] = (in & mask) ? 1 : 0;
    in <<= 1;
  }
}

int main(int argc, char* argv[]){
   int number = 30;
   int len = bit_len(number);
   int digits[len];
   int_to_bin_digit(number,len, digits);
   for( int i =0;i<len;i++){
       printf("%d",digits[i]);
   }
  return 0;
 }
0

Try something like this:

uint8_t * intToBin(int x) {
    uint8_t *bin = (int *) malloc(8);
    uint8_t i = 0;
    int mask = 0x80;
    for (i = 0; i < 8; i++) {
        bin[i] = (x & mask) >> (7-i);
        mask >>= 1;
    }
    return bin;
}

Include <stdint.h> for the declaration of uint8_t. Remember to free the malloc-ed memory if you don't want memory leaks.

M. Shaw
  • 1,742
  • 11
  • 15
  • Not enough memory `int *bin = (int * ) malloc(8);` --> `int *bin = malloc(8 * sizeof *bin);` – chux - Reinstate Monica Jul 23 '15 at 04:24
  • @chux The OP needs 8 bits stored in an array. I should probably change the type of `bin` to `unsigned char` or `uint8_t` instead. The OP needs 8 bits and I'm already allocating 64. There is no reason at all I would need 256 bits of memory to store 8 bits of data. – M. Shaw Jul 23 '15 at 04:28
  • "The OP needs 8 bits and I'm already allocating 64" is not correct. Code was allocating 8 as in `malloc(8)`, which was certainly insufficient memory for 8 `int` - hence the comment. IAC, the `malloc(8)` now is sufficient memory for 8 `uint8_t`. But now it has a new issue: returning a `uint8_t *` that is cast to a `int *`. With 4-byte `int`, the calling code could reference the first 2 of the `int*` array, but certainly OP was expecting 8. – chux - Reinstate Monica Jul 23 '15 at 12:07
0

Using bitwise logic :

for(int i = 0 ; i < 8 ; i++)
{
    bytearray[i] = inputint & pow(2,7-i);
}
ydobonebi
  • 240
  • 2
  • 11
  • You could do it faster with exploiting C unions and structs btw. – ydobonebi Jul 23 '15 at 04:08
  • `sizeof(int)` is 4, not 8. – M. Shaw Jul 23 '15 at 04:11
  • And it should be `pow(2, 7-i)` so the array isn't reversed. – M. Shaw Jul 23 '15 at 04:12
  • @M.Shaw Oops, I was excited about my bits I forgot sizeof is more into bytes – ydobonebi Jul 23 '15 at 04:12
  • `sizeof(int) * 8` is 32. OP said `the maximum array length will not exceed 8 elements`. – M. Shaw Jul 23 '15 at 04:13
  • I think using the modulus approach is faster in terms of math because pow can be expensive – ydobonebi Jul 23 '15 at 04:13
  • You also need to shift the result of the `&` appropriately or the results would be `[0x1, 0x2, 0x4, 0x8]` for 15 instead of `[1, 1, 1, 1]`. – M. Shaw Jul 23 '15 at 04:14
  • The modulus approach is slow as well. Fastest operators are always `>>`, `<<`, `&` which all compile to a single instruction in most instruction sets. You can see GCC's compilation of modulus http://stackoverflow.com/questions/4361979/how-does-the-gcc-implementation-of-module-work-and-why-does-it-not-use-the. – M. Shaw Jul 23 '15 at 04:18
  • @M.Shaw I don't see how given my example shifting would result in correct outcome. I could rewrite it using shift instead of pow() however but I think another answer already did that. and yeah, I suppose modulus would be expensive compared to shift by a good margin – ydobonebi Jul 23 '15 at 04:20
  • Using FP `double pow(double)` for this integer problem is _unusual_. Also, in C, and-ing with a `double` is not allowed. Results in "error: invalid operands to binary & (have 'int' and 'double')" or the like. Suggest `1u << (7-i)` – chux - Reinstate Monica Jul 23 '15 at 11:47
0

This may be helpful:

void binary(unsigned n)
{
    unsigned i;
    for (i = 1 << 31; i > 0; i = i / 2)
        (n & i)?`/*STORE 1*/` : `/*STORE 0*/` ;
}
TryinHard
  • 4,078
  • 3
  • 28
  • 54
0

This should work.

#include <stdio.h>

void intToBin(int dec, int bin[], int numBits){
    for(int i = 0; i < numBits; i++){
        bin[i] = 1 & (dec >> i);
    }
}

void printArr(int arr[], int arrSize){
    for(int i = 0; i < arrSize; i++) {
        printf("%d ", arr[i]);
    }
}

int main(int argc, char* argv[]){
    int bin[32];
    intToBin(-15, bin, 32); 
    printArr(bin, 32);
}
takasoft
  • 1,228
  • 15
  • 15
-1

Recursive Implementation:

(Since you cannot have the prior idea of number of digits(0/1) in the binary format of the given number)

int arr[200]; //for storing the binary representation of num
int i=0; // to keep the count of the no of digits in the binary representation

void calBinary(int n) // function to recalculate
{
   if(n>1)
      calBinary(n/2);
   arr[i++]=n%2;
}
Kaustav Ray
  • 744
  • 6
  • 20