Linked list remove() and free() How can I improve my remove function?  Could someone also give me a solid explanation of the free() function?

Here is my remove function:

void removeData(void *data, struct accList *theList)
{
  if(theList-&gt;head == NULL)                  //nothing can be deleted
    return;
  else if(theList-&gt;head == theList-&gt;tail)          //there is only one element in the    list
  {
    free(theList-&gt;head);
    theList-&gt;head = theList-&gt;tail = NULL;
  }
  else if(data == theList-&gt;head-&gt;data)           //the node to be deleted is the head
  {
    struct accListNode *temp = theList-&gt;head;
    free(theList-&gt;head);
    theList-&gt;head = temp;
    theList-&gt;head-&gt;next = temp-&gt;next;
  }
  else if(data == theList-&gt;tail-&gt;data)      //the node to be deleted is the tail
  {
    struct accListNode *cur;
    for(cur = theList-&gt;head; cur-&gt;next-&gt;next != NULL; cur = cur-&gt;next);
    theList-&gt;tail = cur;
    free(cur-&gt;next);
    cur-&gt;next = NULL;
  }
  else                                     //the node to be deleted is any other node
  {
    struct accListNode *cur;
    for(cur = theList-&gt;head; cur != NULL; cur = cur-&gt;next)
    {  
      if(cur-&gt;data == data)     //this is the node we must delete from theList
      {
        struct accListNode *temp = cur-&gt;next-&gt;next;
        free(cur-&gt;next);
        cur-&gt;next = temp;
        break;
      }
    }
  }
}
First, about free(). If you need memory, you call malloc() and it will give you a pointer that points to a block of memory that is yours now. The OS will (hopefully) take care that no one else will use this memory. But, as with all resources, be it sockets, open files or threads, you will have to relinquish this memory at one time. At the latest, when your application exits. Better, before that, ideally the moment you don't need it anymore. And that's what free() is for. That pointer you got from malloc()? Give it to free() and you're telling the OS that you're done with this particular block of memory. This will allow other programs to reutilize the memory and keeps your memory footprint small. However, that means that you shouldn't use this memory yourself again. The mean thing is that using the memory anyway might not crash your application right away. That's why it's always a good idea to set a pointer to NULL right after freeing it. That way, if you try to use this pointer again, it will crash directly, making it more obvious where the error is.

If you don't free memory you allocated, it's a memory leak. Especially if this happens periodically, it can be a real problem, because the longer your program runs, the more memory it consumes. Memory it doesn't use, but other programs might need. So always free your memory. Use tools like valgrind to check for leaks and other problems.

Now, to your function. I spotted one little error:

struct accListNode *temp = theList-&gt;head;
free(theList-&gt;head);
theList-&gt;head = temp; // Does nothing
theList-&gt;head-&gt;next = temp-&gt;next; // Potential crash


I think the first line should read

struct accListNode *temp = theList-&gt;head-&gt;next;


Otherwise, the third line does nothing (it's just the first line in reverse) and the fourth will sooner or later lead to a crash because you're accessing free'd memory.

Then, there's the second case, where there's only one element in the list. Are you sure you want to remove that element without first checking if it's actually the data that was requested to be removed?

And a small optimization in the last case:

for(cur = theList-&gt;head-&gt;next; cur != theList-&gt;tail; cur = cur-&gt;next)


You've already established that the data to remove isn't in the tail or head, so you don't need to check them again.
The rest is just stylistic:

if(theList-&gt;head == NULL)
    return;


Even if it's only one line, it's good practice to put braces around it:

if(theList-&gt;head == NULL) {
    return;
}


Also, you use struct accList a lot. You can make a typedef like so:

typedef struct accList accList


It looks a little weird, but after that, you can replace all your struct accList with just accList. To better distinguish it from a variable name, I also recommend renaming it to AccList.