Home > Blockchain >  How can I change what a pointer points to within a function in C?
How can I change what a pointer points to within a function in C?

Time:09-27

I'm trying to code a resizable array, which expands when it's full. All functions are working, but the resize one isn't.

int main(void)
{
   int arr[4];
   int *ptr = arr;
   initializeEmptyArray(ptr);
   insertAtIndex(ptr, 0, 4);
   insertAtIndex(ptr, 0, 3);
   insertAtIndex(ptr, 0, 2);
   insertAtIndex(ptr, 0, 1);
   resizeArray(&ptr);
   for (int i = 0; i < capacity; i  )
   {
       printf("%i", arr[i]);
   }
}

This initiates my array [1,2,3,4] and then calls the resize array to test it.

void resizeArray(int **arr)
{
    int *newArr = (int *)malloc(capacity * 2 * sizeof(int));
    for (int i = 0; i < capacity; i  )
    {
        newArr[i] = (*arr)[i];
    }
    for (int i = capacity; i < capacity * 2; i  )
    {
        newArr[i] = EMPTY;
    }
    free(*arr);
    *arr = newArr;
}

The problem is the value of arr when I print it doesn't change to [1,2,3,4,-1,-1,-1,-1] (-1 represents empty). How can I change the pointer to point to this new array?

Capacity stands for the number of elements the array support, initiated as 4 EMPTY is defined as -1, to represent a empty slot in the array.

CodePudding user response:

You can't resize an array. It's size is fixed.

So if you want something that can be resized do:

int arr[4]; --> int* arr = malloc(4 * sizeof *arr);

BTW:

It seems you miss a line like:

capacity = 2 * capacity ;

CodePudding user response:

Hava a look at "realloc", your question sounds like a perfect match

CodePudding user response:

You can not resize an array with automatic storage duration. You can do this with arrays that have allocated storage duration.

So you should remove the array declaration in main and write

int *ptr = malloc( 4 * sizeof( int ) );

or

int *ptr = malloc( capacity * sizeof( int ) );

Also you forgot to change the value of the variable capacity. I suppose that it is not declared as a constant variable.

In this case the function resizeArray can look for example the following way

int resizeArray( int **arr )
{
    int *newArr = realloc( *arr, capacity * 2 * sizeof(int));

    int success = newArr != NULL;

    if ( success ) 
    {
        *arr = newArr;

        for (int i = capacity; i < capacity * 2; i  )
        {
            newArr[i] = EMPTY;
        }

        capacity *= 2;
    }

    return success;
}

Pay attention to that a reallocation of the array can fail. So the function should signal to the caller whether the reallocation was successful.

Also it is not a good idea to use the variable capacity as a global variable.

You could write in main

int capacity = 4;
int *ptr = malloc( capacity * sizeof( int ) );

// ...

and call the function like

resizeArray( &ptr, &capacity );

In this case the function will look the following way

int resizeArray( int **arr, int *capacity )
{
    int *newArr = realloc( *arr, *capacity * 2 * sizeof(int));

    int success = newArr != NULL;

    if ( success ) 
    {
        *arr = newArr;

        for (int i = *capacity; i < *capacity * 2; i  )
        {
            newArr[i] = EMPTY;
        }

        *capacity *= 2;
    }

    return success;
}

CodePudding user response:

The two main issues with the code is that arr is allocated on the stack in main(), and then you free() it in resizerArray(). That is a defect, and I fixed that my heap allocating arr in main() instead. In your loop, you print arr[i] but pass ptr to resizeArray() which is updated, but arr still points to memory that is now free'ed. I fixed this issue by eliminated the ptr variable:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 0

void resizeArray(int **arr, size_t capacity) {
    int *newArr = malloc(2 * capacity * sizeof(int));
    // for (int i = 0; i < 2 * capacity; i  ) {
    //  newArr[i] = i < capacity ? (*arr)[i] : EMPTY;
    // }
    memcpy(newArr, *arr, capacity * sizeof(int));
    memset(newArr   capacity, EMPTY, capacity * sizeof(int));
    free(*arr);
    *arr = newArr;
}

int main(void) {
    size_t capacity = 4;
    int *arr = malloc(capacity * sizeof(int));
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    arr[3] = 4;
    for (int i = 0; i < capacity; i  ) {
        printf("before: %d\n", arr[i]);
    }
    resizeArray(&arr, capacity);
    capacity *= 2;
    for (int i = 0; i < capacity; i  ) {
        printf("after: %d\n", arr[i]);
    }
}

I comment out the loop in resizeArray so you can see how you would do that. The code prints:

before: 1
before: 2
before: 3
before: 4
after: 1
after: 2
after: 3
after: 4
after: 0
after: 0
after: 0
after: 0

Both resizeArray() and the calling code has to know about the factor 2. This is not a great design. Maybe pass in old and new capacity? Or pass in size_t *capacity that can be updated if you want to hard-code the factor in resizeArray()? Remember to check the return value of malloc() to ensure it did not fail.

See realloc() for the standard way to resize heap allocated memory, and calloc() for how to get pre-initialized memory.

  • Related