remove kth last element from singly-linked list - Follow up This code is a revised version of implementation which asked for an improvement. Original question is asked here:
remove kth last element from singly-linked list
credits to: Toby, Andreas, Arkadiusz
What has changed:

remove length from xllist struct
check if k is bigger than list length on the fly

Code:
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;stdint.h&gt;

typedef struct llnode
{
    int value;
    struct llnode *next;
} llnode;

typedef struct xllist
{
    llnode * head;
    llnode * tail;
} xllist;

bool create_node(xllist *list, int value)
{
    llnode *node = malloc(sizeof *node);
    if(!node)
    {
        return false;
    }

    node-&gt;value = value;
    node-&gt;next = NULL;
    if(!list-&gt;head)
    {
        list-&gt;head = node;
        list-&gt;tail = node;
    }
    list-&gt;tail-&gt;next = node;
    list-&gt;tail = node;
    return true;
}

bool del_element_from_last(xllist *llist, int k)
{
    //window with 2 pointers, length of k
    //prev is the prev node to the window
    llnode *prev;
    llnode *last;
    int len;  //list length

    if(llist-&gt;head)
    {
        last = llist-&gt;head;
        prev = llist-&gt;head;
        len = 1;
    }

    for(; last; last=last-&gt;next)
    {
        len++;
        if(len &gt; k+1)
            prev = prev-&gt;next;
    }

    if(len &lt; k) //len is smaller than k
    {
        return false;
    }

    if(len == k)  //means del 1st element from the list
    {
        llist-&gt;head = llist-&gt;head-&gt;next;
    }

    //remove first node of the window
    printf(&quot;deleted element:%d \n&quot;, prev-&gt;next-&gt;value);
    prev-&gt;next = prev-&gt;next-&gt;next;
    return true;
}

int main(void)
{
    xllist llist = {NULL, NULL};

    for(int i=0; i&lt;100; i++)
    {
        if(!create_node(&amp;llist, 100+i))
            printf(&quot;create fail\n&quot;);
    }

    del_element_from_last(&amp;llist, 15);
}
In the function del_element_from_last, when removing the first element of the list, you update llist-&gt;head. However, when removing the last element of the list, you do not update llist-&gt;tail.
If keeping track of the tail of the list is only intended for building the list, and is not intended to be updated by the function del_element_from_last, then you should not pass the entire struct xllist to the function del_element_from_last. Rather, you should change the function signature to the following, so that the function only has access to the head:
bool del_element_from_last( xlnode **pp_head, int k )

According to the task description, k is guaranteed to be smaller than the list. This means that the list is guaranteed to be not empty. In that case, the line
if(llist-&gt;head)
in the function del_element_from_last is redundant, because the condition will always be true.
On the other hand, defensive programming is good programming style. Therefore, it may still be appropriate to keep it.
However, if you decide to keep it, your program should handle both cases properly. If the condition is false, your program will cause undefined behavior, because you read the uninitialized value of last. Therefore, you should probably instead immediately return false when the condition is false.
An alternative to the if statement would be to use the assert macro, like this:
assert( llist-&gt;head );
That way, you don't have to provide code to handle both cases. Instead, a diagnostic error message will appear if the variable does not have the expected value (only on debug builds though, not on release builds).