cmallocfreememory-reallocation

Is there a way to change an array size using malloc and free functions only?


As homework, I have to write a function that changes an array's size using malloc and free functions only.

I know how to do it with realloc, but I don't know how to do it with malloc.

typedef struct{
    int *tab;
    int size;
}arr;

and I need to write this function :

void changeSizeDyn(arr *Dyn_arr, int size){
    //
}

As mentioned in the homework: it requires only one reallocation and only one memory release, and only one copy of the elements from the old array. I searched a lot but only found results using realloc.

Is it even possible to do that without using realloc?


Solution

  • struct Arr {
            int *tab;
            ptrdiff_t nmemb;
    };
    

    Let's say you allocated the array like this initially:

    struct Arr x;
    
    x.nmemb = 7;
    x.tab = malloc(sizeof(*x.tab) * x.nmemb);
    

    You should realloc it with this function:

    void change_size_dyn(struct Arr *dyn_arr, ptrdiff_t nmemb)
    {
            struct Arr old;
            ptrdiff_t cp_nmemb;
    
            if (!dyn_arr)
                    return;
            old = *dyn_arr;
    
            if (nmemb <= 0)
                    goto err;
            dyn_arr->tab = malloc(sizeof(*dyn_arr->tab) * nmemb);
            dyn_arr->nmemb = nmemb;
    
            cp_sz = MIN(old.nmemb, nmemb);
            memcpy(dyn_arr->tab, old.tab, cp_nmemb);
            free(old.tab);
    
            return;
    err:
            dyn_arr->tab = NULL;
            dyn_arr->nmemb = 0;
            free(old.tab);
    }
    

    Which should be called this way:

    change_size_dyn(&x, 9);
    

    You can use this function even for the first allocation (although you should set to NULL and 0 both values first). You also don't need to add a free; an input of 0 would do it for you, just like realloc would do:

    int main(void)
    {
            struct Arr x = {0};
    
            change_size_dyn(&x, 5);
            /* ... */
            change_size_dyn(&x, 9);
            /* ... */
    
    cleanup:
            change_size_dyn(&x, 0);
            return 0;
    }
    

    If you pass a structure where dyn_arr->nmemb is already a negative value (shouldn't happen), the behaviour is undefined (that negative value would go into memcpy, which would be wrapped into a very high size_t, which would overflow the arrays). I didn't want to check for that because it would be unnecessary in any non-buggy scenario.