2

I have a char array

char *data[]= {"11", "22", "33", "44", "55"};

How can I add some extra items to it in the end? data[]="66";

I'd like a dynamic array in C.

Thanks

3
  • 1
    In C you have to specify the size of an array. You cannot have a dynamic array. What you want to do is create functions to treat the array as an arraylist and create a new one every time you add objects and it overflows. Commented Dec 1, 2011 at 8:37
  • You'd probably want to use a list. You can create a new, larger array each time you want to add something, copy old elements and drop the old table, but that's not the way to go. Commented Dec 1, 2011 at 8:39
  • 1
    You should invest some money in a books or read an online tutorial... Commented Dec 1, 2011 at 8:40

3 Answers 3

9

Arrays created using the [] syntax are not dynamic, the length is set at compile-time and cannot change.

UPDATE: Actually, C99 adds so-called "variable-length arrays", which can get their length at run-time. After they've been initialized, however, they can't shrink or expand so the below still applies.

However, an array is trivially expressed when you have pointers: an array can be represented as a pointer to the first element, and a length.

So, you can create a new array by dynamically allocating memory using malloc():

size_t array_length = 3;
int *array = malloc(array_length * sizeof *array);

if(array != NULL)
{
  array[0] = 11;
  array[1] = 22;
  array[2] = 33;
}

You cannot use the {} list of elements here, that's only usable when initializing arrays declared using the [] syntax.

To grow the array, you can use the realloc() function to re-allocate the memory and copy the old values over:

size_t new_length = array_length + 1;
int *bigger_array = realloc(array, new_length * sizeof *bigger_array);

if(bigger_array != NULL)
{
  bigger_array[new_length - 1] = 44;
  /* We have successfully grown the allocation, remember the new address. */
  array = bigger_array;
  array_length = new_length;
}

Note that every time you call malloc() (or realloc()), it can return NULL if it failed to allocate the requested block. That's why the if statements are needed. I cut the initial size down a bit from your example to reduce the number of assignment-lines needed, to make the example shorter.

To make the above more efficient, typical dynamical array code uses two length values: one for the actual array (how many values are in the array right now) and one for the memory (how many values to we have room to store). By making the latter value grow in chunks, the total number of memory allocations can be cut down a bit, at the cost of some memory of course.

Sign up to request clarification or add additional context in comments.

4 Comments

Didn't know realloc exists. You just made me realize how much easier my life could be the last years.
man malloc, my friend. You can also check if the original pointer matches the new one returned by realloc() so you don't have to copy if not needed.
What is the proper way to free array?? free(array); ?? or do I need to free(array[i]); before free(array); ??
The proper way in your example is free(array) ,when you would have an array of pointers then you have to free(array[i]) and after that free(array)
2

vc_vector

vc_vector* vector = vc_vector_create(0, sizeof(const char *), NULL);

vc_vector_push_back(vector, "11");
vc_vector_push_back(vector, "22");
vc_vector_push_back(vector, "33");

for (int i = 0; i < vc_vector_count(vector); ++i) {
  printf("%s ", (const char*)vc_vector_at(vector, i));
}

// output: 11 22 33

vc_vector_release(vector);

1 Comment

+1 for the only answer that references a true implementation of a dynamic array. VLAs are not dynamic arrays.
1

Here is a macro based solution for a dynamic array in C with a very nice syntax to use. Works for any data type.

#include <stdio.h>
#include <stdlib.h>
#include <wondermacros/array/dynamic_array.h>

int main()
{
  int* elems = NULL; /* Initialize a dynamic array. */
  W_DYNAMIC_ARRAY_PUSH(elems, 1, 2, 3, 4); /* Push some elements. */

  /* Iterate all elements. */
  W_DYNAMIC_ARRAY_FOR_EACH(int, e, elems) {
    printf("%d\n", e);
  }

  W_DYNAMIC_ARRAY_FREE(elems); /* Free the array only this way since there is a hidden header. */
}

The library uses Boost pre-processor library so Boost library needs to be there at build time.

2 Comments

Could you explain your answer a bit more?
There is a hidden header node which saves the size and the allocation size of the dynamic array. The dynamic array is accessed through the third field of the real dynamic array struct. PUSH, FOR_EACH, FREE and other macros know it, and when they need to access size and allocation size, they use negative offsets for the base pointer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.