1

I'm writing a C program that takes in a num (decimal, hex, or octal) and converts it into two's complement binary form.

The algorithm should be right since I had use it elsewhere before but I am confused on how to return the array of int's of 0's and 1's.

My understanding is I have to use malloc to allocate the memory space for this new array but I'm not sure how to do it syntax-wise.

This is what I have so far:

char *itob (int num, int size) {
        int binary[size];
        binary[size] = (int *)malloc(size);
        for (int i=0; i<size; i++) {
                binary[i] = 0;
        }
        int decimal = num;
        int counter = 0;

        if (decimal > -32768 && decimal < 32767) {
                if (decimal < 0) {
                        decimal = 65536 + decimal;
                }
                while (decimal>0) {
                        binary[counter] = decimal%2;
                        decimal = decimal/2;
                        counter++;
                }
        }

        return binary;
}

The parameter num is the number to convert and size is the number of bits I want to print.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    1) Never cast the malloc result in C. The compiler does it for you. This also helps you make it right: 2) The malloc result is a pointer assign it to a pointer variable: `int *binary = malloc(sizeof(int)*size);` 3) Make you return type the same as your `binary` variable type. – harper Mar 07 '21 at 15:19
  • I tried `int *binary = malloc(sizeof(int)*size);` and I get the error `variable-sized object may not be initialized`? –  Mar 07 '21 at 15:21
  • Remove the line `int binary[size];` – harper Mar 07 '21 at 15:23
  • Hmm..I did that –  Mar 07 '21 at 15:25
  • Remove line 'binary[size] = (int *)malloc(size);'. Variable binary has automatic storage – tstanisl Mar 07 '21 at 17:43

2 Answers2

3

If you want to allocate and return an array of int variables, you need your function to return an int* value (not char*); then, inside that function simply allocate a local int* pointer and return that, when you've calculated and assigned its elements.

Note that the size of the memory block to be allocate should be the number of elements (the size argument, in your case) multiplied by the size of each element (which will be sizeof(int), for your code).

You can access the elements in the allocated data using the [] (index) operator on the returned pointer, just as though that were an array.

int* itob(int num, int size) // Returns an int array, not a char array
{
//  int binary[size];
//  binary[size] = (int*)malloc(size);
    int* binary = malloc(size * sizeof(int)); // Note: Don't cast the "malloc" return!
    for (int i = 0; i < size; i++) {
        binary[i] = 0;
    }
    int decimal = num;
    int counter = size - 1; // Your code will return the digits in reverse order!

    if (decimal > -32768 && decimal < 32767) {
        if (decimal < 0) {
            decimal = 65536 + decimal;
        }
        while (decimal > 0) {
            binary[counter] = decimal % 2;
            decimal = decimal / 2;
            counter--; // See the comment on the initialization of "counter"
        }
    }

    return binary;
}

Don't forget to release the allocated memory (in the calling module) by calling free() on the pointer returned by itob (after you've finished working with it).

On the casting (or not) of the malloc return (in C), see: Do I cast the result of malloc?.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Wow thank you! I was wondering, how would I change the code if I were to want it to return char? I just realized my header file says to return a char array, but I'm not sure how that would be possible because I am doing integer calculations? Would you be able to point me in the right direction? –  Mar 07 '21 at 15:23
  • @Sarah Read point 2) of my comment. The return type must match the type of the variable `binary`. If you need that return type, change `binary`s type. – harper Mar 07 '21 at 15:24
  • @Sarah Converting to a `char` array is simple: Basically, you just need to change the assignment line from `binary[counter] = decimal % 2;` to `binary[counter] = (char)((decimal % 2) + '0');` Also, `sizeof(int)` (in `malloc`) will then be `sizeof(char)` - which is `1` by definition. – Adrian Mole Mar 07 '21 at 15:25
  • Cool! Can I ask why I need to do + '0'? –  Mar 07 '21 at 15:28
  • The characters representing the digits, '0' thru '9' have values that are *not* 0 thru 9 - though they are, by definition, contiguous. In ASCII (the most common system used), the '0' character has a value of 48 and '9' has 57. Using the `'0'` format makes your code work on non-ASCII systems, as well. – Adrian Mole Mar 07 '21 at 15:30
  • Also, I keep getting an error saying `variable-sized object may not be initialized` for `char *binary[size] = malloc(sizeof(char)*size);`. As @harper said I deleted any other initializations of the array but I still get this error.. –  Mar 07 '21 at 15:30
  • @Sarah Look at my code carefully. There is no `[size]` in the `int* binary = malloc(...` line. You want a ***single*** pointer, not an array of pointers. – Adrian Mole Mar 07 '21 at 15:31
  • Oh, I see now. I missed that, it's a bit early in the morning for me :( Thank you so much! I understand now –  Mar 07 '21 at 15:34
  • Follow up question, I hope that's okay, for some reason nothing is printing as the result of this code. I'm testing with `itob('A', 8)` but it doesn't print anything. I keep thinking it's because my code is only for decimals, but I'm not sure how I'd change it to detect if it's hex, octal, etc.. –  Mar 07 '21 at 15:45
  • Why are you passing a character literal? Your function takes an `int` first argument. But you should make a new question, perhaps, for using different bases (hex or octal). – Adrian Mole Mar 07 '21 at 15:48
  • @sarah: please keep in mind, this is not a tutorial site. If you need help learning C, please consider reading a(n) (e)book or follow a good online tutorial. There might also be courses at your local university/college or similar institute, depending on your location. Expecially C is not a good language to learn by trial&error because of the nature of undefined behaviour (please look it up). There is a Q&A on SO recommending C books, check it out. – too honest for this site Mar 07 '21 at 16:15
0

regarding:

int binary[size];
    binary[size] = (int *)malloc(size);

this allocates size bytes, which will not work for you. Suggest:

int *binary = malloc( size * sizeof( int ) );
if( ! binary )
{
    perror( "malloc failed" );
    exit( EXIT_FAILURE );
}

no casting of the returned value from malloc() because in C, the returned type is void* which can be assigned to any pointer AND binary[size] is an array, not a pointer. I.E. the cast, besides being unneeded, is wrong

user3629249
  • 16,402
  • 1
  • 16
  • 17