Creating a linked list of n length I wrote this working code to create a linked list of a given length and print each node's values.

#include &lt;stdlib.h&gt; //NULL
#include &lt;stdio.h&gt;  //printf

typedef struct Node {
    int val;
    struct Node* next;
} node;

node* make_ll(int len){
    node* head = malloc(sizeof(node));
    node* cur = head;
    for (int i = 0; i &lt; len; i++) {
        cur-&gt;val = i;
        cur-&gt;next = (i &lt; (len - 1)) ? malloc(sizeof(node)) : NULL;
        cur = cur-&gt;next;
    }
    return head;
}

void print_ll(node* head){
    node* cur = head;
    while (cur != NULL) {
        printf("Node: %d @ %p\n", cur-&gt;val, cur);
        cur = cur-&gt;next;
    }
}

int main(){
    node* ll = make_ll(4);
    print_ll(ll);
    free(ll);
}


Output:



Node: 0 @ 0x81b010
Node: 1 @ 0x81b030
Node: 2 @ 0x81b050
Node: 3 @ 0x81b070


I'm wondering if there's a practical way to write make_ll() so that, rather than checking if we've reached the last desired node on every pass of the for loop and setting cur-&gt;next accordingly, as done here with line 14:



cur-&gt;next = (i &lt; (len - 1)) ? malloc(sizeof(node)) : NULL;


we can simply malloc() for each "next" node until the last, setting it equal to NULL.

I'm new to C, mostly influenced by Python, and the things I tried to no avail were the result of my ignorance of the languages' difference in scope rules. It would probably be noisy to try to reproduce them here.

Any pointers in the right direction?
naked malloc calls

Note that malloc() simply allocates memory - you have no guarantees about what the newly allocated memory contains. For that reason it is better to write a function which both allocates and initializes an new object, i.e.:

node* newNode(int v) {
  node* p = (node*) malloc( sizeof(node) );
  // assume malloc never fails
  p-&gt;val = v;
  p-&gt;next = NULL;
  return p;
}


Now use newNode() where you are using malloc() directly.

make_ll

First of all, does your make_ll work for len = 0?

For comparison, here is a recursive solution for make_ll:

node* make_ll(int len) {
  if (len &lt;= 0) {
    return NULL;        // a list of length 0
  } else {
    node *tail = make_ll(len-1);
    node *head = newNode(len);
    head-&gt;next = tail;
    return head;
  }
}


And here is a way I would transform this into a loop which avoids double checking the exit condition:

node* make_ll(int len) {
  if (len &lt;= 0) {
    return NULL;
  }
  node* head = newNode(len);
  node* last = head;
  for (; len &gt; 0; --len) {
    node* n = newNode(len);
    last-&gt;next = n;
    last = n; 
  }
  return head;
}


The idea is to keep track of the last node in the chain so you can update its next field when you create a new node.