1
\$\begingroup\$

I'm currently learning C/C++ and I saw this question on Reddit on how to create a linked from an array and decided that would make a good exercise for learning the absolute basics of C, so without looking at the answers I wrote this.

Anyways, preamble aside, here's the code:

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

typedef struct Node Node;

typedef struct Node {
    int data;
    Node *next;
} Node;

Node *array_to_list(int32_t array[], int32_t length) {
    if (length <= 0) {
        return NULL;
    }

    Node* tail = NULL;

    for (int32_t i = length - 1; i >= 0; i--) {
        Node* current = (Node*) malloc(sizeof(Node));
        current->data = array[i];
        current->next = tail;
        tail = current;
    }

    return tail;
}

void free_list(Node *head) {
    while (head != NULL) {
        Node *next = head->next;
        free(head);
        head = next;
    }
}

int main() {
    int array[] = { 1, 2, 3, 4, 5 };
    Node *list = array_to_list(array, 5);

    Node *current = list;
    while (current != NULL) {
        printf("%d\n", current->data);
        current = current->next;
    }

    free_list(list);

    return 0;
}

As of now this is all inside main.c and I didn't implement any other methods a linked list would normally have, I'm just trying to see if I'm doing things right

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Use the correct types

Use size_t instead of int32_t for the array size and index. Using int32_t will limit it to arrays containing 2,147,483,647 elements even if you compiled it for 64-bit mode.

Also, note that it does not make sense to check if i or length is less than zero since it is unsigned.

Node* array_to_list(int array[], size_t length) {
    // ...
    for (size_t i = 0; i < length; i++) {
        // ...
    }
    return tail;
}

Check if malloc was successful

You cannot simply assume that there will be enough memory available.

Putting it all together:

Node* array_to_list(int array[], size_t length) {
    Node* tail = NULL;
    for (size_t i = 0; i < length; i++) {
        Node* current = malloc(sizeof(Node));
        if (!current)
        {
            fprintf(stderr, "Out of memory error");
            exit(EXIT_FAILURE);
        }
        current->data = array[length - 1 - i];
        current->next = tail;
        tail = current;
    }
    return tail;
}

int main() {
    int array[] = { 1, 2, 3, 4, 5 };
    struct Node* list = array_to_list(array, sizeof(array) / sizeof(array[0]));
    for (Node* node = list; node; node = node->next)
        printf("%d\n", node->data);
    free_list(list);
}
\$\endgroup\$
6
  • \$\begingroup\$ Totally forgot about checking if malloc failed or not, but I think I'll still have to check if size isn't 0, because I need to loop over the array in reverse (so the linked list created is in the same order as the array), and if the length is 0 it'd underflow to 4294967295 and as such I'd index into an invalid place in the array \$\endgroup\$
    – MindSwipe
    Commented Nov 21, 2021 at 21:03
  • \$\begingroup\$ @MindSwipe, see my latest edit. You don't have to check if length is 0. array[length - 1 - i] reverses the array. \$\endgroup\$
    – jdt
    Commented Nov 21, 2021 at 21:15
  • \$\begingroup\$ Node* current = malloc(sizeof(Node)); could be Node* current = malloc(sizeof(*current)); \$\endgroup\$
    – ggorlen
    Commented Nov 21, 2021 at 22:03
  • \$\begingroup\$ @ggorlen potato, patata ;-) \$\endgroup\$
    – jdt
    Commented Nov 21, 2021 at 23:16
  • \$\begingroup\$ Not quite -- there's benefit to the second approach. See sizeof style: sizeof(type) or sizeof variable? \$\endgroup\$
    – ggorlen
    Commented Nov 21, 2021 at 23:27

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.