Quick general purpose linked list in C I want to use it when some function needs to return a list of something. Is it working as I think it should or is there undefined behavior somewhere? What I really tried to achieve is something like a templated &lt;list&gt; from C++ - for any type. I'm not sure if there is a standard solution/include/library for this.

list.h

#pragma once

#include &lt;stddef.h&gt;

struct list_handler
{
    struct list_node *head;
    struct list_node *tail;
    size_t count;
};

struct list_node
{
    void *data;
    struct list_node *next;
};

void list_init(struct list_handler *list);
void list_add(struct list_handler *list, void *data);
void list_free(struct list_handler *list);
void list_foreach(struct list_handler *list, void (*foreach_function)(void *));


list.c

#include "list.h"

#include &lt;stdlib.h&gt;

void list_init(struct list_handler *list)
{
    list-&gt;head = NULL;
    list-&gt;tail = NULL;
    list-&gt;count = 0;
}

void list_add(struct list_handler *list, void *data)
{
    struct list_node *new_node = malloc(sizeof(struct list_node));

    new_node-&gt;data = data;
    new_node-&gt;next = NULL;

    if (list-&gt;count &gt; 0)
    {
        list-&gt;tail-&gt;next = new_node;
    }
    else
    {
        list-&gt;head = new_node;
    }

    list-&gt;tail = new_node;

    ++list-&gt;count;
}

void list_free(struct list_handler *list)
{
    struct list_node *current = list-&gt;head;
    struct list_node *previous;

    while (current != NULL)
    {
        previous = current;
        current = current-&gt;next;

        free(current);

        list-&gt;head = current;
        --list-&gt;count;
    }

    list-&gt;tail = NULL;
}

void list_foreach(struct list_handler *list, void (*foreach_function)(void *))
{
    struct list_node *current = list-&gt;head;

    while (current != NULL)
    {
        (*foreach_function)(current-&gt;data);
        current = current-&gt;next;
    }
}


Usage:

void list_print(void *data)
{
    int *temp = (int*) data;
    printf("%d\n", *temp);
}

void list_free_data(void *data)
{
    int *temp = (int*) data;
    free(temp);
    data = NULL;
}

int main(int argc, char *argv[])
{
    struct list_handler list;
    list_init(&amp;list);

    for (size_t i = 0; i &lt; 3; ++i)
    {
        int *data = malloc(sizeof(int));
        *data = i;
        list_add(&amp;list, data);
    }

    list_foreach(&amp;list, list_print);
    list_foreach(&amp;list, list_free_data);

    list_free(&amp;list);

    return 0;
}
The list_free has a small error.
Whether the function should free the list is up to the API design. Maybe you did not want dangling pointers. Then the name should be better list_clear.

void list_free(struct list_handler *list)
{
    struct list_node *current = list-&gt;head;
    struct list_node *previous;

    while (current != NULL)
    {
        previous = current;
        current = current-&gt;next;

        //- free(current);
        free(previous); //+

        list-&gt;head = current;
        --list-&gt;count;
    }

    list-&gt;tail = NULL;
    free(list); //+
}


Freeing the data is a non-list issue, misleading, especially with a void*.

void list_free_data(void *data)
{
    //int *temp = (int*) data;
    //free(temp);
    //data = NULL;
    free(data);
}


Assigning NULL to data has no effect.

However if you want to free the list with freeing the data:

list_foreach(list, free);
list_free(list);
free(list);


The list_foreach is limited as it must work with side-effects, storing results or other context in global variables. Better provide a for-each with an additional parameter. So bad coding style is not inevitable.

For the remainder: I like APIs to provide a full set of operations, that is with a remove too.