title: Trouble swapping nodes in doubly linked list
body: <p>I am trying to swap two nodes in a doubly linked list using C. It is working if I pass in some values, for example the head and tail of the list, and some in between. However, on others the value of one seems to be overwritten by the other and I am thrown into a loop.</p>
  
  <p>Node/List:</p>
  
  <pre><code>struct node //node for linked list
  {
      unsigned long int *id;
      char *firstname, *lastname, *department;
      float *gpa;
      struct node *next, *prev;
  };
  struct linked_list //doubly linked_list data structure
  {
      struct node *head, *tail;
  };
  </code></pre>
  
  <p>I can successfully add nodes to the list and move the tail to the newly added node.</p>
  
  <pre><code>void *add_node(struct node **tail, unsigned long int *id, char *first, char *last, char *dept, float *gpa) //create a node, add to tail
  {
      struct node *newStudent = (struct node*)malloc(sizeof(struct node));
      newStudent-&gt;firstname = (char*)malloc(strlen(first)+1);
      newStudent-&gt;lastname = (char*)malloc(strlen(last)+1);
      newStudent-&gt;department = (char*)malloc(strlen(dept)+1);
      newStudent-&gt;id = (unsigned long int*)malloc(sizeof(unsigned long int));
      newStudent-&gt;gpa = (float*)malloc(sizeof(float));
  
      *(newStudent-&gt;id) = *id;
      *(newStudent-&gt;gpa) = *gpa;
  
      strcpy(newStudent-&gt;firstname, first);
      strcpy(newStudent-&gt;lastname, last);
      strcpy(newStudent-&gt;department, dept);
  
      newStudent-&gt;next = NULL;
      if(tail) //not the first node in the list
      {
          newStudent-&gt;prev = *tail;
          (*tail)-&gt;next = newStudent;
          *tail = newStudent;
      }
      else //head of the list
          return newStudent;
  }
  </code></pre>
  
  <p>And finally, my swap function:</p>
  
  <pre><code>void *_swap(struct node **x, struct node **y, struct linked_list **list)
  {
      struct node *temp = (struct node*)malloc(sizeof(struct node));
      memcpy(temp, *x, sizeof(struct node));
  
      if( (*y)-&gt;prev ) /// if y has a previous...
      {
          (*x)-&gt;prev = (*y)-&gt;prev;
          (*y)-&gt;prev-&gt;next = *x;
      }
      else
          (*x)-&gt;prev = NULL;
  
      if( (*y)-&gt;next )  /// if y has a next...
      {
          (*x)-&gt;next = (*y)-&gt;next;
          (*y)-&gt;next-&gt;prev = *x;
      }
      else
          (*x)-&gt;next = NULL;
  
      if( temp-&gt;prev) /// if original x has a previous...
      {
          (*y)-&gt;prev = temp-&gt;prev;
          temp-&gt;prev-&gt;next = *y;
      }
      else
          (*y)-&gt;prev = NULL;
  
      if(temp-&gt;next) /// if original x has a next...
      {
          (*y)-&gt;next = temp-&gt;next;
          temp-&gt;next-&gt;prev = *y;
      }
      else
      (*y)-&gt;next = NULL;
  
      free(temp);
  
      if((*list)-&gt;head == *x &amp;&amp; (*list)-&gt;tail == *y)
      {
          (*list)-&gt;head = *y;
          (*list)-&gt;tail=*x;
      }
      else if((*list)-&gt;head == *y &amp;&amp; (*list)-&gt;tail == *x)
      {
          (*list)-&gt;head = *x;
          (*list)-&gt;tail=*y;
      }
      else if((*list)-&gt;head == *x)
          (*list)-&gt;head = *y;
      else if((*list)-&gt;head == *y)
          (*list)-&gt;head = *x;
      else if((*list)-&gt;tail == *x)
          (*list)-&gt;tail = *y;
      else if((*list)-&gt;tail == *y)
          (*list)-&gt;tail = *x;
  
      printf("%s %s %s %s %s\n\n\n\n", (*list)-&gt;head-&gt;firstname, (*list)-&gt;head-&gt;next-&gt;firstname, (*list)-&gt;head-&gt;next-&gt;next-&gt;firstname, (*list)-&gt;head-&gt;next-&gt;next-&gt;next-&gt;firstname, (*list)-&gt;head-&gt;next-&gt;next-&gt;next-&gt;next-&gt;firstname);
  }
  </code></pre>
  
  <p>When I call something like 
              temp->next->prev = *y;
  it sometimes seems to overwrite the value of, in this case, x, instead of simply reassigning the linked_list pointer to y.</p>
  
  <p>I am able to build my list just fine:</p>
  
  <pre><code>struct linked_list *list = (struct linked_list*)malloc(sizeof(struct linked_list));
  list-&gt;head = (struct node*)malloc(sizeof(struct node));
  list-&gt;tail = (struct node*)malloc(sizeof(struct node));
  unsigned long int *id = malloc(sizeof(unsigned long int));
  *id = 343232;
  float gpa = 3.2;
  list-&gt;head = add_node(NULL, id, "Matthew", "D", "CECS", &amp;gpa);
  list-&gt;tail = list-&gt;head;
  
  add_node(&amp;(list-&gt;tail), id, "John", "X", "PNY", &amp;gpa);
  add_node(&amp;(list-&gt;tail), id, "Rebecca", "H", "ECE", &amp;gpa);
  </code></pre>