Singly Linked List Implementation in C I'm preparing for an interview soon, and I've written the following linked list implementation from scratch. 

This is all self-taught, and I'm still working on my C. I feel that the implementation is correct (if someone catches a corner case though, that would be great!), and I'm looking for feedback on best C practices.

For example: Is the spacing excessive? Are 1-line control flow statements okay? Is the constructor implementation idiomatic?

Header file:

#ifndef Interview_Prep_SLL_h
#define Interview_Prep_SLL_h

typedef struct SLLNode
{
    int val;
    struct SLLNode* next;
} SLLNode;

SLLNode* new_SLLNode(int val);
SLLNode* SLLappend(SLLNode* head, int val);
SLLNode* SLLinsert(SLLNode* head, int val, int ind);
SLLNode* SLLdelete(SLLNode* head, int val);
SLLNode* SLLreverse(SLLNode* head);
void SLLprint(SLLNode* head);

#endif


Source file:

// constructor
SLLNode* new_SLLNode(int val)
{
    SLLNode* head = malloc(sizeof(SLLNode));
    head-&gt;val = val;
    head-&gt;next = NULL;
    return head;
}

// add node to end
SLLNode* SLLappend(SLLNode* head, int val)
{
    if (head == NULL) return new_SLLNode(val);

    SLLNode* curr = head;

    while (curr-&gt;next != NULL) curr = curr-&gt;next;

    curr-&gt;next = new_SLLNode(val);

    return head;
}

// insert node at index (position) ind
SLLNode* SLLinsert(SLLNode* head, int val, int ind)
{
    if (head == NULL &amp;&amp; ind &gt; 0) return head;
    if (head == NULL &amp;&amp; ind == 0) return new_SLLNode(val);

    SLLNode* curr = head;
    int count = 0;

    while (curr != NULL &amp;&amp; count &lt; ind - 1)
    {
        curr = curr-&gt;next;
        count++;
    }

    if (curr == NULL) return head;

    SLLNode* temp = curr-&gt;next;
    SLLNode* new = new_SLLNode(val);

    curr-&gt;next = new;
    new-&gt;next = temp;

    return head;
}

SLLNode* SLLdelete(SLLNode* head, int val)
{
    if (head == NULL) return head;

    if (head-&gt;val == val) return head-&gt;next;

    SLLNode* curr = head;

    while (curr-&gt;next != NULL &amp;&amp; curr-&gt;next-&gt;val != val) curr = curr-&gt;next;

    if (curr-&gt;next == NULL) return head;

    SLLNode* temp = curr-&gt;next;
    curr-&gt;next = curr-&gt;next-&gt;next;
    free(temp);

    return head;
}

SLLNode* SLLreverse(SLLNode* head)
{
    if (head == NULL) return head;
    if (head-&gt;next == NULL) return head;

    SLLNode* curr = head;
    SLLNode* next = curr-&gt;next;
    SLLNode* nextnext = next-&gt;next;

    while (true)
    {
        if (curr == head) curr-&gt;next = NULL;

        next-&gt;next = curr;
        curr = next;
        next = nextnext;

        if (nextnext == NULL) return curr;

        nextnext = nextnext-&gt;next;
    }
}

// print values of nodes separated by spaces
void SLLprint(SLLNode* head)
{
    while (head != NULL)
    {
        printf("%d ", head-&gt;val);
        head = head-&gt;next;
    }
    printf("\n");
}
Overall this seems fine: a classing linked list implementation in C.
A couple of things can be simplified or improved here and there.



Instead of testing head == NULL twice:


if (head == NULL &amp;&amp; ind &gt; 0) return head;
if (head == NULL &amp;&amp; ind == 0) return new_SLLNode(val);



It would be better to eliminate this duplication and do it only once:

if (head == NULL) {
    if (ind &gt; 0) return NULL;
    if (ind == 0) return new_SLLNode(val);
}


Notice that I also changed return head to return NULL.
I know that head is NULL there,
but it's more explicit this way.

I have a feeling that after the while loop that iterates until ind to insert an element, when you do this:


if (curr == NULL) return head;



Possibly you really meant this instead:

if (curr == NULL) return curr;
// or
if (curr == NULL) return NULL;


I could be wrong, but perhaps not using explicit NULLs somehow led to mistakes like this. (I assume it was a mistake to return head when trying to insert beyond end + 1 of the linked list, which indicates a likely bug in the caller.)




  Is the spacing excessive?


No, I think it's just right.


  Are 1-line control flow statements okay? 


They are ok. But keep in mind that if/for/while statements without a { ... } block can lead to nasty bugs, like in this famous example.
Some static analysis tools flag a warning for such statements.