Making an array smaller with realloc, losing first element

I've been trying to make an example program using calloc and realloc and I've come across an issue where, when I make an array of integers smaller, it seems to remove the first element instead of the last one.

int *m = (int*)calloc(2, sizeof(int));

    *m = 1;     
    *(m+1) = 2;   
    printf("\tInt 1: %d\n", m[0]);
    printf("\tInt 2: %d\n\n", *(m+1));

// REALLOC

printf("How many elements the array have? ");
scanf("%d", &num);

*m = (int *)realloc(m, num * sizeof(int));

    printf("ARRAY NOW HAS %d PLACES\n\n\t", num);

    for(i = 0; i < num; i++) {

        m[i] = i + 1;
        printf("%d ", m[i]);

    }

// DELETING MEMBERS OF AN ARRAY

while((d < 0) || (d > num)) {

    printf("\n\nChoose which position of the previous array should be deleted (0 = first): ");
    scanf("%d", &d);
}

printf("\nUPDATED ARRAY:\n\n");

for(i = d; i < num - 1; i++) {

    m[i] = m[i + 1];
}

*m = (int *)realloc(m, (num - 1)*sizeof(int));

num--;

for(i = 0; i < num; i++) {

    printf("%d ", m[i]);
}

An example of the program output would be:

        Int 1: 1
        Int 2: 2

How many elements the array have? 17
ARRAY NOW HAS 17 PLACES

        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Choose which position of the previous array should be deleted (0 = first): 6

UPDATED ARRAY:

10620272 2 3 4 5 6 8 9 10 11 12 13 14 15 16 17

And if I include the last member of the array that should have been deleted (in this case m[16]) it shows:

10620272 2 3 4 5 6 8 9 10 11 12 13 14 15 16 17 17

Of course, I'm not entirely sure what's happening but it seems like it's just removing the value of m[0]?

Thanks in advance for any help!

2 answers

  • answered 2018-07-12 01:05 dasblinkenlight

    The reason the initial value gets modified is that you are assigning it:

    *m = (int *)realloc(m, num * sizeof(int));
    

    should be

    m = realloc(m, num * sizeof(int));
    

    Your code should also produce a warning, telling you that an assignment of a pointer to an array element containing ints is invalid. Fixing this warning should have fixed your problem.

    Note that an assignment of the form

    m = realloc(m, ...);
    

    where m is used on both sides of realloc is inherently unsafe, because realloc could potentially return NULL - for example, when there is not enough memory to allocate. Blind assignment to m would render the old value of m inaccessible, preventing proper deallocation. In production you should assign realloc's result to a temporary, then check it for NULL, and only then assign the result back to m.

  • answered 2018-07-12 04:13 chux

    In addition to @dasblinkenlight good answer, when reducing the allocation size and the re-allocation fails (a rare event), code can simple continue with the original pointer.

    Suggested re-write, assuming num > 0:

    // *m = (int *)realloc(m, num * sizeof(int));
    void *t = realloc(m, sizeof *m * num);
    if (t) {
      m = t;
    }