Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resizing an array in C

Tags:

arrays

c

resize

Say I assigned an array like so:

char* array[]={"This"};

And then later I wanted to assign array[ ] a new value so that it stores "This" and "That," is there a way that I could change the size of array so that it could hold a new number of values?

like image 298
Sam Avatar asked Oct 16 '12 15:10

Sam


3 Answers

No, you can't change the size of an array. You could use a dynamically allocated list of char* instead and realloc() as required:

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

int main()
{
    char** array = malloc(1 * sizeof(*array));

    if (array)
    {
        array[0] = "This";

        printf("%s\n------\n", array[0]);

        char** tmp = realloc(array, 2 * sizeof(*array));
        if (tmp)
        {
            array = tmp;
            array[1] = "That";

            printf("%s\n", array[0]);
            printf("%s\n", array[1]);
        }

        free(array);
    }
    return 0;
}

See online demo: https://ideone.com/ng00k.

like image 96
hmjd Avatar answered Oct 19 '22 18:10

hmjd


There is no way to resize an array. You can simply create a new array of size 2, then copy all the data from the previous one to the new one. realloc does it for you with dynamic memory. The better way is to use data structures such as LinkedLists or Vectors which you can find more about online.

like image 22
Ben Avatar answered Oct 19 '22 19:10

Ben


You cannot resize array objects.

You would have to dynamically allocate the memory for array and extend it using realloc. Example:

size_t current_size = 0;

char **array = malloc((current_size + 1) * sizeof *array);
if (array)
{
  array[current_size++] = "This";
}
...
/**
 * If realloc cannot extend the buffer, it will return NULL and leave
 * the original buffer intact; however, if we assign NULL back to array,
 * we lose our handle to the original buffer, causing a memory leak, so
 * we assign the result to a temporary variable.
 */
char **tmp = realloc(array, (current_size + 1) * sizeof *array)
if (tmp)
{
  array = tmp;
  array[current_size++] = "That";
}
else
{
  // realloc failed to extend the buffer; original buffer
  // is left intact.
}

Caveats:

realloc is a relatively expensive call, so you (generally) don't want to extend your buffer one element at a time like I did here. A more common strategy is to pick an initial starting size that covers most cases, and if you need to extend the buffer, double its size.

You could abstract the resize operation into a separate function, like so:

int addItem(char ***arr, char *newElement, size_t *count, size_t *bufSize)
{
  if (*count == *bufSize)
  {
     // we've run out of room; extend the buffer
     char **tmp = realloc(**arr, 2 * *bufSize * sizeof **arr);
     if (tmp)
     {
       *arr = tmp;
       *bufSize *= 2;
     }
     else
     {
       // could not extend the buffer; return failure code
       return 0;
     }
  }
  (*arr)[(*count)++] = newElement;
}

and call it as

#define N ... // initial array size

char **array = malloc(N * sizeof *array);
size_t bufSize = N;
size_t count = 0;
...
if (addItem(&array, "This", &count, &bufSize))
  printf("# elements = %zu, buffer size = %zu\n", count, bufSize);

if (addItem(&array, "That", &count, &bufSize))
  printf("# elements = %zu, buffer size = %zu\n", count, bufSize);

This is all untested and off the top of my head; no warranties express or implied. But it should be enough to point you in the right direction.

like image 45
John Bode Avatar answered Oct 19 '22 19:10

John Bode