0

I allocate memory with calloc() but then it get's cleared when I call calloc to allocate more memory, later in the program. I calloc num1bin inside of conv2bin and then it get's cleared back to all 0's when I calloc my luiArray. Is this how it's supposed to work? Am I missing something?

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

typedef int bool;

void printBinary(bool* bin, int size, FILE* outfile)
{
    for(int i=0; i<size; ++i)
    {
        fprintf(outfile, "%d", bin[i]);
    }
}

void printHex(char* hex, int size, FILE* outfile)
{
    for(int i=0; i<size; ++i)
    {
        fprintf(outfile, "%c", hex[i]);
    }
}

bool* conv2bin(int num)
{
    bool* bin = (bool*) calloc(1, 16);
    if(num > 65535 || num < 0)
    {
        fprintf(stderr, "NUMBER NOT AVAILABLE FOR 16BIT UNSIGNED BINARY\n");
        exit(1);
    }
    int j = 0;
    for(int i=15; i>=0; --i, j++)
    {
        if(num >= (int) pow(2, i))
        {
            bin[j] = 1;
            num -= (int) pow(2,i);
        }
        else
        {
            bin[j] = 0;
        }
    }
    if(num != 0)
    {
        fprintf(stderr, "FUNCTION FAILED\n\n");
        printBinary(bin, 16, stderr);
        fprintf(stderr, "\n");
        exit(1);
    }

    return bin;
}

char* conv2hex(bool* bin)
{
    char* hex = (char*) calloc(1, 5);
    int j=0;
    for(int i=0; i<16; i+=4, ++j)
    {
        int hchar = 0;
        if(bin[i] == 1)
        {
            hchar += 8;
        }
        if(bin[i+1] == 1)
        {
            hchar += 4;
        }
        if(bin[i+2] == 1)
        {
            hchar += 2;
        }
        if(bin[i+3] == 1)
        {
            hchar += 1;
        }

        if(hchar < 10)
        {
            hex[j] = (char)(((int)'0')+hchar);
        }
        else if(hchar == 10)
        {
            hex[j] = 'A';
        }
        else if(hchar == 11)
        {
            hex[j] = 'B';
        }
        else if(hchar == 12)
        {
            hex[j] = 'C';
        }
        else if(hchar == 13)
        {
            hex[j] = 'D';
        }
        else if(hchar == 14)
        {
            hex[j] = 'E';
        }
        else if(hchar == 15)
        {
            hex[j] = 'F';
        }
    }
    return hex;
}

int multiply(int num1, int num2)
{
    for(int i=0; i<num2; ++i)
    {
        int carry;
        while(num2 != 0)
        {
            carry = (num1 & num2) << 1;
            num1 ^= num2;
            num2 = carry;
        }
    }
    return num1;
}

int divide(int num1, int num2, int* remain)
{
    int quotient = 0;
    if(num1 == num2)
    {
        (*remain) = 0;
        return 1;
    }
    else if(num1 < num2)
    {
        (*remain) = num1;
        return 0;
    }
    do
    {
        num2 <<= 1;
        quotient <<= 1;
    } while(num2 <= num1);

    return quotient = quotient + divide((num1 - num2), num2, remain);
}

int main(int argc, char **argv)
{
    FILE* infile;
    FILE* outfile;
    infile = fopen(argv[1], "r");
    outfile = fopen(argv[2], "w");

    //check file integrity
    if(infile == NULL)
    {
        fprintf(stderr, "CANNOT OPEN INPUT FILE!\n");
        exit(1);
    }
    if(outfile == NULL)
    {
        fprintf(stderr, "CANNOT OPEN OUTPUT FILE!\n");
        exit(1);
    }

    int num1, num2;
    fscanf(infile, "%d\n%d", &num1, &num2);

    fprintf(outfile, "%d\t%d\n", num1, num2);

    /*SIMULATING LUI AND ORI*/
    bool* num1bin = conv2bin(num1);
    bool* num2bin = conv2bin(num2);

    //print binary numbers
    printBinary(num1bin, 16, outfile);
    fprintf(outfile, "\t");
    printBinary(num2bin, 16, outfile);
    fprintf(outfile, "\n");
    printBinary(num1bin, 16, stderr);

    //allocate memory and write binary numbers into it
    bool* luiArray = (bool*) calloc(1, 32);
printBinary(num1bin, 16, stderr);
    int j=0;
    for(int i=15; i>=0; --i, ++j)
    {
        luiArray[i] = num1bin[j];
    }
    //print out array after first 16 loaded into it
    printBinary(luiArray, 32, outfile);
    fprintf(outfile, "\n");
    j=16;
    for(int i=31; i>=16; --i, ++j)
    {
        luiArray[i] = num1bin[j];
    }

    printBinary(luiArray, 32, outfile);
    fprintf(outfile, "\n");
    free(luiArray);

    /*BITWISE MULTIPLY AND DIVIDE*/
    int product = multiply(num1, num2);
    fprintf(outfile, "%d * %d = %d\n", num1, num2, product);
    int quotient, remain;
    divide(num1, num2, &remain);
    fprintf(outfile, "%d / %d = %d (%d)\n", num1, num2, quotient, remain);

    /*LOGICAL OPERATORS*/
    int andresult = num1 & num2;
    bool* ares = conv2bin(andresult);
    char* hexand = conv2hex(ares);
    printBinary(ares, 16, outfile);
    fprintf(outfile, "\t");
    printHex(hexand, 4, outfile);
    fprintf(outfile, "\n");
    free(ares);

    int orresult = num1 | num2;
    bool* ores = conv2bin(orresult);
    char* hexor = conv2hex(ores);
    printBinary(ores, 16, outfile);
    fprintf(outfile, "\t");
    printHex(hexor, 4, outfile);
    fprintf(outfile, "\n");
    free(ores);

    int xorresult = num1 ^ num2;
    bool* xres = conv2bin(xorresult);
    char* hexxor = conv2hex(xres);
    printBinary(xres, 16, outfile);
    fprintf(outfile, "\t");
    printHex(hexxor, 4, outfile);
    fprintf(outfile, "\n");
    free(xres);

    int notresult = ~num2;
    bool* nres = conv2bin(notresult);
    char* hexnot = conv2hex(nres);
    printBinary(nres, 16, outfile);
    fprintf(outfile, "\t");
    printHex(hexnot, 4, outfile);
    fprintf(outfile, "\n");
    free(nres);

    free(num1bin);
    free(num2bin);

    fclose(infile);
    fclose(outfile);
    free(hexand);
    free(hexor);
    free(hexxor);
    free(hexnot);
    return 0;
}

Use a text file with just two positive numbers (78 and 123 are what I'm using) separated by a return for input. Any text file for output.

Sorry for the confusion. Thank you for the help. And I'll update the pow() to bitshift at some point.

jboulter11
  • 152
  • 1
  • 2
  • 12

2 Answers2

4

This code:

typedef int bool;

means that sizeof(bool) == sizeof(int). Your allocations assume that sizeof(bool) == 1. However, sizeof(int) > 1. Hence your program invokes undefined behaviour by writing off the end of an array.

Some other comments:

  1. pow() performs floating point arithmetic. That's really not appropriate. You should use bitwise shifting.
  2. Don't cast the return value of malloc().
  3. Are you quite sure that you want to typedef a type named bool? That seems a little imprudent to me. I would suggest that you include stdbool.h and use the standard C bool. Of course, you'll still want to use sizeof() rather than making any assumptions.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

After accept answer

Agree the size is wrong as @David Heffernan fine answer reports.

To avoid getting the size wrong in the first place, do not hard-code size. Let the compiler derive it by using sizeof *bin.

 void *calloc(size_t nmemb, size_t size);

 // bool* bin = (bool*) calloc(1, 16);
 bool* bin = calloc(16, sizeof *bin);

Minor:
1) Subtle issues may occur in select compilers concerning the order of calloc() parameters. Use number_of_elements, size_of_one_element)
2) No need to cast calloc() return value.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256