2

I tried to create dynamically growing array I did with realloc. I have example below but I do not understand how this code works by using malloc.

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

int main(void) {
    int cnt = 0;
    double *numbers = NULL;
    double newnum;
    while (scanf("%lf", &newnum) == 1 && newnum != -1) {
        double *newarr = (double*) malloc(sizeof(double) * (cnt+1)); 
        for (int i = 0; i < cnt; ++i)
            newarr[i] = numbers[i]; 
        free(numbers); 
        numbers = newarr;
        numbers[cnt] = newarr; 
        ++cnt;
    }

    for (int i = cnt-1; i >= 0; --i) {
        printf("%f\n", numbers[i]);
    }

    free(numbers);

    return 0;
}
Emil
  • 73
  • 1
  • 12

1 Answers1

2

realloc() is the same as malloc(), memcpy(), free() all in one function (*).

The loop in your code effectively replaces memcpy()

        // memcpy(newarr, numbers, cnt * sizeof *newarr);
        for (int i = 0; i < cnt; ++i)
            newarr[i] = numbers[i]; 

(*) realloc() may be smart enough to avoid the memcpy() and free() and reuse memory.


How can I implement this in my code?

It helps to encapsulate the pointer and the total/used elements in a structure.

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

struct DynArray {
    double *data;
    size_t m; // total
    size_t n; // used
};

void growarray(struct DynArray *x) {
    size_t newsize = x->m * 13 / 8 + 1; // use phi aproximation 13/8
    double *newarr = realloc(x->data, newsize * sizeof *x->data);
    if (!newarr) exit(EXIT_FAILURE);
    fprintf(stderr, "INFO: realloc'ed with %d elements.\n", (int)newsize);
    x->data = newarr;
    x->m = newsize;
}

int main(void) {
    struct DynArray numbers = { 0 };
    double newnum;
    while (scanf("%lf", &newnum) == 1 && newnum != -1) {
        if (numbers.n == numbers.m) growarray(&numbers);
        numbers.data[numbers.n] = newnum;
        numbers.n++;
    }

    for (int i = numbers.n - 1; i >= 0; --i) {
        printf("%f\n", numbers.data[i]);
    }

    free(numbers.data);

    return 0;
}

See code running on ideone or previous version without growarray function or previous version with cnt

pmg
  • 106,608
  • 13
  • 126
  • 198
  • I understood. It seems it is better to use realloc. – Emil Oct 27 '18 at 09:02
  • Make sure you [use `realloc()` correctly](https://stackoverflow.com/questions/3850749/does-realloc-overwrite-old-contents/3850798#3850798) – pmg Oct 27 '18 at 09:27
  • Also realize that memory allocation is a slow operation and you should instead use a x2, or better, golden ratio to double or ~x1.618 your array size respectively, when you do need more space, and not every single iteration... – Purple Ice Oct 27 '18 at 10:26
  • @EmilBədrəddinli: nicely spotted!! `cnt` is a left over from the original code. It was replaced by `numbers.n`. It is safe to delete and I've edited my answer. – pmg Oct 27 '18 at 12:12
  • Clearly explained. Thanks – Emil Oct 27 '18 at 12:20