Well, the original array needs to be malloc'ed, rather than on the stack. Then you can use realloc:

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

int main()
{
    int * numbers = malloc(6*sizeof(int));

    for(int ii = 0; ii < 6; ++ii) {
        numbers[ii] = 5;
    }

    numbers = realloc(numbers, 7*sizeof(*numbers));
    if(!numbers) {
        printf("Memory allocation failed, sorry dude!\n");
        exit(1);
    }

    numbers[6] = 7;

    for(int ii = 0; ii< 7; ++ii) {
        printf("%d\n", numbers[ii]);
    }

    free(numbers);
}
Answer from user14717 on Stack Overflow
🌐
Mccue
mccue.dev › pages › 3-22-19-how-to-append-to-an-array-in-c
How to append to an array in C
Conceptually an array is not a good fit for continual appending. If you want to do an operation like that you would be best off writing or finding your own "ArrayList" kind of wrapper. is there a way to find the index of the last item in the list
🌐
Reddit
reddit.com › r/c_programming › can we create arraylists in c where we can access an index directly?
r/C_Programming on Reddit: Can we create ArrayLists in C where we can access an index directly?
October 12, 2020 -

I know how to make a LinkedList in C but I'm struggling to understand how an ArrayList would be implemented in C - especially the addition and direct access parts

Top answer
1 of 5
23
A homebrew ArrayList would work the way Vectors do in C++ behind the scenes: arrays! (Note, this is also how Java implements ArrayLists behind the scenes as well). They maintain an array member variable with a certain amount of space. As new elements are added they manually shift items around to insert them into certain spots, or just add them at the back if that's all you need. But if they realize the member array does not have enough storage, they will create a new array (typically double the size or something like that) and then manually copy all the elements over to that new array. Because all the elements are stored in a member array, which has instant "random access," this makes index access far more efficient than it is for linked lists. However, it makes insertions into the middle of the list and deletions more inefficient - in theory.
2 of 5
4
Firstly I'd say that, while its totally educational and interesting to try implementing such things in C, I would experiment with avoiding using it for general C stuff! Vectors / Lists are structures with fast indexed access, unpredictable appending times (due to occasional re-allocation), and potentially wasteful memory footprint. Consider a simple array of up to 100 chars: char test_array[100]; With this, we can access anywhere between array[0] and array[99]. If we need more, we malloc() the required memory, copy everything over, and reassign test_array to the new memory! However, malloc() could potentially fail, or take a (relative) while... (There is also realloc() which automates some of this). So that's dynamic length handled! Hopefully you can see that it sacrifices speed and potentially memory. The C++ std::vector is often padded out at the start using resize() to make sure these sporadic malloc()s don't slow down your code... So you are back to using the maximum amount of memory anyway! Also, when std::vector does need to grow, it grows by a whole lot, hoping to avoid growing again too soon... As you can imagine, hitting a limit when you just want to append 1 entry could waste a few bytes! This is one of the many reasons embedded C++ avoids std::vector. To keep track of the used length, and the maximum capacity, we just need more variables. So behind the scenes, you could do a ArrayList of floats with: EDIT: see the replies for corrections to my dodgy untested code! Fixed for posterity :) float* array; size_t array_length; size_t array_capacity; With a little extra arithmetic, and a commitment to never exceed capacity (or realloc as you go, if you really want an application that grows in RAM footprint) you can do it all: array_capacity = 1000; array = malloc(array_capacity * sizeof(float)); array_size = 0; array[array_size] = 1.5f; array_size++; Of course this could be wrapped in functions - you could even make a generic structure using an array of bytes, and looking up the index * byte_stride. Honestly though, lists are usually parts of systems, and I prefer to let systems handle their own arrays :) As I said, theres nothing wrong with ArrayLists in themselves - heck you could be writing a high level language's backend for all I know! But if you want to understand their implementation, in the context of why C doesn't provide them, hopefully this reply was somewhat helpful :) Up front allocation, avoiding malloc after initialisation, low indirection... all these things help turn C code from chunky corporate software to efficient, Mars-rover-friendly routines :)
🌐
Stack Overflow
stackoverflow.com › questions › 64594206 › need-help-making-an-arraylist-add-at-in-c
Need help making an ArrayList Add At in C - Stack Overflow
October 29, 2020 - It should be void** data = realloc(list->arr, sizeof(*list->arr) * (list->size + 1)); ... 1. Add a dummy element (maybe NULL) at the end of array 2. Shift elements of array afte the point to insert 3. Store value to insert ...
Top answer
1 of 3
12

First, a word on naming:

The name you've chosen for your type, _arraylist is a bad name for a library interface type. Names starting with _ are not pleasant to work with in user code. They are commonly used inside library internals. Better names would be ArrayList or array_list.

Actually, in your usage example, you have ArrayList. Does this mean that in the header, which is not included here, you have something like this?

typedef _arraylist ArrayList;

If you did define an opaque type in the header, like above, that would be a good practice. But then you should not use any reference to _arraylist in your code. Use always the typedef'd name to avoid confusion.

The function name prefix should also follow exactly the name of the type, so for ArrayList all functions should be prefixed the ArrayList_, e.g.:

ArrayList * ArrayList_create();

Also, I would suggest that you avoid tightlypacked names, like in arraylist_getsize(). Adding an underscore to separate words makes them a lot more readable. E.g.: ArrayList_get_size().

Problems with memory:

Lets look at arraylist_create():

struct _arraylist *arraylist_create() {
    struct _arraylist *list = malloc(sizeof(struct _arraylist));
    assert(list != NULL);
    list->size = 0;
    list->data = calloc(2, sizeof(void *));
    assert(list->data != NULL);
    list->data[0] = NULL;
    return list;
}

First thing unusual here is the assertions. Assertions are not the proper way to handle a memory allocation failure. Plus, they are commonly disabled on release builds, so on release, if you'd happen to run out of memory, the program would just crash silently. You should probably return a NULL in this case (maybe also log to stderr) and let the caller handle this error as he/she sees fit.

Second problem here is with calloc(). You are allocating 2 void pointers, however, size is set to zero. I don't really get the point of this. Since your structure is more like and array of arrays then a list, what you should do is allocate the array of pointers with some predefined default size, then allocate the individual arrays as needed. Growing the array of pointers on demand. How arraylist_create() should look like:

ArrayList * ArrayList_create() {
    ArrayList *list = malloc(sizeof *list);
    if (list == NULL) {
        return NULL;
    }

    list->size = 0;
    list->data = calloc(INITIAL_BASE_ARRAY_SIZE, sizeof(void *));
    if (list->data == NULL) {
        free(list); // Don't leek memory here!
        return NULL;
    }

    return list;
}

Another big memory issue is the constant re-allocations done by arraylist_add() and arraylist_remove().

Remove should not shrink the sequence. Keep that space around if the array grows again in the future. You can add an explicit way to let the user shrink the storage if necessary (a la std::vector::shrink_to_fit()).

Adding to the array can be made to run in amortised-constant time if you pre-allocate storage with a larger size then the requested. (Again inspired by the STL vector).

sizeof mistake:

This will not return what you expect:

size_t arraylist_getsizeof(struct _arraylist *list) {
    /* Returns the size of the internal array in memory */
    return sizeof(*list->data);
}

The sizeof operator always returns the size of the type it is applied to. It cannot infer the size of an array pointed by a pointer, because it is a compile-time operation. arraylist_getsizeof() will always return the same value, the size of a void pointer, which will be 4 or 8, depending on the architecture.

Use assertions to check for invariants:

You should assert that the *list parameter of every function is valid. This is a precondition of every function, they cannot work without a valid ArrayList instance, so you should assert that once the function enters.

Miscellaneous:

You don't need to check if the pointer is null before freeing it. In arraylist_deallocate() the if (list->data != NULL) check is uneeded.

arraylist_deallocate would be more symmetric with arraylist_create if named arraylist_destroy.

2 of 3
7

Lets talk about perfomance

What if you need to use your list very frequently?

Let's look closer at function arraylist_add; if I need a list with 1 million bytes, which is 1MB, it will reallocate your data struct member 1 million times.

It is lowest part of your list!

Suggestions

Allocate memory by chunks, e.g., C++ std::vector uses increasing size of appended chunks depending on current size of std::vector.

This will increase perfomance it few times in purpose of adding new elements.

Lets talk about code as is

Try to implement some elegant, but simple program flow.

Create value type (int) ArrayList, which will allocate memory by chuncks instead of reallocate full array, and add some list behaviour under the hood. I mean list of chunks, you still need to manage it.

Here is my solution with with example of using chuncks of data for each node instead of reallocating nodes. Different chunck size may be best for one of purposes: writing, reading long arrays; r\w short arrays; removing elements; etc.

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

typedef struct ArrayList ArrayList;
typedef ArrayList* ArrayListPtr;

struct ArrayList {
    size_t capacity;
    size_t size;
    int *data;
    ArrayListPtr parent;
    ArrayListPtr child;
};

const size_t ARRAY_LIST_CHUNCK_SIZE = 64;

ArrayListPtr array_list_create_with_parent_and_chunck_size(ArrayListPtr parent,
                                                           size_t chunck_size) {
    ArrayListPtr result = (ArrayListPtr)calloc(sizeof(ArrayList), 1);
    result->parent = parent;
    result->capacity = chunck_size;
    result->data = (int*)malloc(sizeof(int) * chunck_size);
    return result;
}

ArrayListPtr array_list_create_with_parent(ArrayListPtr parent) {
    return array_list_create_with_parent_and_chunck_size(
        parent, ARRAY_LIST_CHUNCK_SIZE
    );
}

ArrayListPtr array_list_create() {
    return array_list_create_with_parent_and_chunck_size(
        NULL, ARRAY_LIST_CHUNCK_SIZE
    );
}

void array_list_push_back(ArrayListPtr list, int value) {
    if (list->size >= list->capacity) {
        if (!list->child) {
            list->child = array_list_create_with_parent(list);
        }
        array_list_push_back(list->child, value);
    } else {
        list->data[list->size++] = value;
    }
}

int* array_list_get_value_by_index(ArrayListPtr list, size_t index) {
    if (index >= list->capacity || index >= list->size) {
        if (list->child) {
            return array_list_get_value_by_index(list->child,
                                                 index - list->size);
        } else {
            return NULL;
        }
    }
    return list->data + index;
}

int main(int argc, char *argv[]) {
    ArrayListPtr list = array_list_create();
    for (int i = 0; i < 100*1000; ++i) {
        array_list_push_back(list, i);
    }
    size_t test[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,31,32,33,63,64,65,999,1000};
    for (int i = 0; i < sizeof(test) / sizeof(size_t); ++i) {
        int* result = array_list_get_value_by_index(list, test[i]);
        if (result) {
            printf("list[%ld] = %d\n", test[i], *result);
        } else {
            printf("Can't get value by index %ld\n", test[i]);
        }
    }
}
🌐
Quora
quora.com › How-can-I-append-to-an-array-in-C
How to append to an array in C - Quora
Answer (1 of 8): Depends what your array is. If your array is array of characters, called string, then using strcat() function will append text at the end of existing one. [code]char String[100] = "string"; strcat(String, " appended"); [/code]Result of above will be: “string appended”. ...
Find elsewhere
🌐
W3Schools
w3schools.com › c › c_arrays.php
C Arrays
To create an array, define the data type (like int) and specify the name of the array followed by square brackets []. To insert values to it, use a comma-separated list inside curly braces, and make sure all values are of the same data type:
🌐
Medium
medium.com › @FixBuisness › can-you-append-to-an-array-in-c-e42a59410e03
Can You Append To An Array In C? | by FixBuisness FAQ | Medium
May 31, 2022 - If you want to append, you need to use a data structure such as the list in Python. In this case, there is an append() method that allows you to do this. Array#append() is an Array class method which add elements at the end of the array.
🌐
Reddit
reddit.com › r/learnprogramming › how to use append in c
r/learnprogramming on Reddit: How to use append in C
October 4, 2022 -

Hi, so I'm a new C user and I found this code online that prints how many times each character in a string is used. So if the input is hello, it prints

'h' = 1

'e' = 1

'l' = 2

'o' = 1

but what if I want to store each of those words and the times it has been used in a list? So in python I know I can use a for loop and append each string, but how would I do that in C? So like, if the input is "hello", I want to create two lists, list 1 = ['h','e','l','o'] and list 2 would be the amount of times it has been used so list 2 = [1,1,2,1] so integers.

#include <stdio.h>
#include <string.h>
 
int main()
{
    char s[1000];  
    int  i,j,k,count=0,n;
 
    printf("Enter  the string : ");
    scanf("%s", s);
     
    for(j=0;s[j];j++);
	 n=j; 
    
	printf(" frequency count character in string:\n");

    for(i=0;i<n;i++)  
    {
     	count=1;
    	if(s[i])
    	{
		
 		  for(j=i+1;j<n;j++)  
	      {   
	    	
	        if(s[i]==s[j])
    	    {
                 count++;
                 s[j]='\0';
	     	}
	      }  
	      printf(" '%c' = %d \n",s[i],count);
	   
       }
	   
	   
 	} 
 	 
     
    return 0;
}

🌐
GeeksforGeeks
geeksforgeeks.org › c language › c-program-to-insert-an-element-in-an-array
C Program to Insert an Element in an Array - GeeksforGeeks
3 weeks ago - If you want to explore array manipulation and other data structures, the C Programming Course Online with Data Structures provides hands-on examples and exercises. If you are inserting an element at the end, there's no need for shifting elements. You can directly add the element at the next ...
🌐
DEV Community
dev.to › bekhruzniyazov › creating-a-python-like-list-in-c-4ebg
Creating a Python-like list in C - DEV Community
August 11, 2021 - ... // if you are planning on using several lists, it's better to create an init function void init(string_list *list) { list->list = calloc(1, sizeof(char *)); list->length = 0; }
🌐
Reddit
reddit.com › r/learnprogramming › is there a way to add new elements to an array after initializing it? (c++)
r/learnprogramming on Reddit: Is there a way to add new elements to an array after initializing it? (C++)
October 2, 2022 -

I was making a program that needs to create a list of numbers, however this number greatly varied with the input, and there’s no closed expression for how long the list would need to be in terms of the input. Something like a linked list would’ve worked nicely but I do not believe there’s an analog of that in c++. I just made a string and would add the numbers after converting them into a string and created a method to read the string like an array which definitely is not very efficient. I’m pretty new/bad at c++ so I apologize if this is a stupid question.

🌐
Quora
cstdspace.quora.com › How-to-create-an-array-of-linked-lists-in-C
How to create an array of linked lists in C - C Programmers - Quora
Quora is a place to gain and share knowledge. It's a platform to ask questions and connect with people who contribute unique insights and quality answers.
🌐
Tpoint Tech
tpointtech.com › add-element-in-array-in-c
Add Element in Array in C - Tpoint Tech
March 17, 2025 - Add Node to Linked List in C · How to Add two Array in C · Algorithm in C language · Add Digits of Number in C · Add Element in Array in C · Add String in C · Add Two Matrices in C · Add two numbers using Pointer in C · Order of Complexity in C · Pattern Matching Algorithm in C ·
🌐
Quora
quora.com › How-do-I-create-an-array-of-linked-lists-in-C-Ive-looked-at-many-tutorials-get-the-concept-visually-but-simply-dont-understand-the-code-that-allows-me-to-implement-it
How to create an array of linked lists in C - Quora
Answer (1 of 4): Is your question: How do I populate the elements of an array? or With what do I populate the elements of an array with in order to have an array of linked lists? [I would populate each element with the value of the variable pointing to the first element of each array. Each elem...
🌐
Tutorial Teacher
tutorialsteacher.com › csharp › csharp-arraylist
C# ArrayList (With Examples)
var arlist1 = new ArrayList(); var arlist2 = new ArrayList() { 1, "Bill", " ", true, 4.5, null }; int[] arr = { 100, 200, 300, 400 }; Queue myQ = new Queue(); myQ.Enqueue("Hello"); myQ.Enqueue("World!"); arlist1.AddRange(arlist2); //adding arraylist in arraylist arlist1.AddRange(arr); //adding array in arraylist arlist1.AddRange(myQ); //adding Queue in arraylist ... The ArrayList class implements the IList interface. So, elements can be accessed using indexer, in the same way as an array. Index starts from zero and increases by one for each subsequent element. An explicit casting to the appropriate types is required, or use the var variable.