Filter a Linked List in Place in C I have created the following function which filters a linked list in place
(here it removes all instances of the element k), but it could easily be modified to take a function pointer as an argument and filter on something else.
Any ideas on how to improve the code?
typedef struct list_integer {
    type value;
    struct list_integer *next;
} list_integer;

list_integer *removeKFromList(list_integer * l, int k)
{

    if (!l)
    return l;
    while (l &amp;&amp; l-&gt;value == k)
    l = l-&gt;next;
    if (!l)
    return l;


    list_integer *p = l;
    list_integer *q = l-&gt;next;

  scan_in:
    if (q) {
    if (q-&gt;value != k) {
        list_integer *t = q;
        q = q-&gt;next;
        p = t;
        goto scan_in;
    } else {
        goto scan_out;
    }
    }

  scan_out:
    if (q) {
    if (q-&gt;value != k) {
        p-&gt;next = q;
        p = q;
        q = q-&gt;next;
        goto scan_in;
    } else {
        q = q-&gt;next;
        goto scan_out;
    }
    } else {
    p-&gt;next = q;
    }
    return l;

}
Table of contents (in no particular order)
Indent your code properly!
Don't use goto for something so routine. Unless you're writing a c compiler and intend to compete with gcc or clang or you're Andrei Alexandrescu... don't use goto at all!
while loop/for loop can be used to accomplish what you need instead of goto.
Fix memory leaks. If you're in place modifying a linked list, the nodes that are removed from the list have to have their memory free'd. (In general, this is the assumption going off solely your function prototype. It's possible that all the nodes are statically allocated and it's not this function's responsibility to free them but I'm assuming the more usual case.)
Use comments to explain what you're doing. Although this isn't super complicated, since it's pretty low level, comments are a good idea.
Checking for NULL, IMO it's better to do an explicit check with == NULL rather than !l. Although it is the same and is a popular choice among C programmers (I used to do it too, it made me feel smart)... it's hard to read and is not a good idea. Personally, I only use !l to check for bool's. Others may disagree.
Better variable names. This can cut down on the amount of stuff that has to be explained in comments. Renamed p to previous and q to current. (If you really don't wanna type so much -- prev and cur)
typedef struct list_integer {
    type value;
    struct list_integer *next;
} list_integer;

list_integer *removeKFromList(list_integer * l, int k)
{

    if (l == NULL) return NULL; // empty list becomes empty list

    // remove the occurrences of k at the beginning
    while (l != NULL &amp;&amp; l-&gt;value == k) { 
        list_integer* temp = l;
        l = l-&gt;next;
        free(temp); // deallocate memory
    }

    if (l == NULL) return NULL; // list of only k's becomes empty list

    // already checked in the while loop. l-&gt;value != k
    list_integer *previous = l;
    list_integer *current = l-&gt;next;

    while (current != NULL) {
        if (current-&gt;value != k) {
            previous = current;
            current = current-&gt;next;
        } else {
            while (l != NULL &amp;&amp; l-&gt;value == k) { // remove continuous occurrences of k
                list_integer* temp = current;
                current = current-&gt;next;
                free(temp); // deallocate memory
            }
            previous-&gt;next = current;
            if(current != NULL) {
                previous = current;
                current = current-&gt;next;
            }   
        }
    }

    return l;
}

The version above keep's the OP's optimisation of not modifying the next pointer (ie p-&gt;next) multiple times if there are multiple continuous k's.
Version without this optimisation is a bit simpler
typedef struct list_integer {
    type value;
    struct list_integer *next;
} list_integer;

list_integer *removeKFromList(list_integer * l, int k)
{

    if (l == NULL) return NULL; // empty list becomes empty list

    // remove the occurrences of k at the beginning
    while (l != NULL &amp;&amp; l-&gt;value == k) { 
        list_integer* temp = l;
        l = l-&gt;next;
        free(temp); // deallocate memory
    }

    if (l == NULL) return NULL; // list of only k's becomes empty list

    // already checked in the while loop. l-&gt;value != k
    list_integer *previous = l;
    list_integer *current = l-&gt;next;

    while (current != NULL) {
        if (current-&gt;value != k) {
            previous = current;
            current = current-&gt;next;
        } else {
            list_integer* temp = current;
            current = current-&gt;next;
            previous-&gt;next = current;
            free(temp); // deallocate memory
        }
    }

    return l;
}
```