Swap elements of two structures

401 Views Asked by At

I have simplified my question to this small C program. Please note that I am learning C on my own. I a having real trouble with pointers!

#include <stdio.h>
#include <stdlib.h>

typedef struct Elmt_ {
    int *i;
    struct Elmt_ *next;
} E;

void swap_1(E *x, E *y) {
    int *temp = NULL;
    temp = x->i;
    x->i = y->i;
    y->i = temp;
}

void swap_2(E *x, E *y) {
    int *temp=NULL;
    temp = malloc(sizeof(int));
    *temp = *(x->i);
    *(x->i) = *(y->i);
    *(y->i) = *temp;
}

int main() {
    E *p, *q, *r, *s;

    int a, b;
    a = 8;
    b = 50;

    p = malloc(sizeof(E));
    q = malloc(sizeof(E));
    p->i = &a;
    p->next = NULL;

    q->i = &b;
    q->next = NULL;
    printf("Initially, *(p->i)=%d *(q->i)=%d\n", *(p->i), *(q->i));
    swap_1(p,q);
    printf("After swap_1, *(p->i)=%d *(q->i)=%d\n", *(p->i), *(q->i));

    r = malloc(sizeof(E));
    s = malloc(sizeof(E));
    r->i = &a;
    s->i = &b;
    printf("Initially, *(r->i)=%d *(s->i)=%d\n", *(r->i), *(s->i));
    swap_2(r,s);
    printf("After swap_2, *(r->i)=%d *(s->i)=%d\n", *(r->i), *(s->i));
    return 0;
}

**Question:**In the above program, is swap_1 or the swap_2 the right way to swap the integer value pointed to by i ?

I see that both these functions seem to swap the values given as arguments correctly.

$ ./a.out
Initially, *(p->i)=8 *(q->i)=50
After swap_1, *(p->i)=50 *(q->i)=8

Initially, *(r->i)=8 *(s->i)=50
After swap_2, *(r->i)=50 *(s->i)=8
2

There are 2 best solutions below

5
AudioBubble On

Function swap_1 swaps the pointer values, not the pointed values.

Function swap_2 swaps the pointed values, but yields a memory leak.

In order to swap the pointed values cleanly, you can simply do:

void swap_3(E *x, E *y) {
    int temp;
    temp = *(x->i);
    *(x->i) = *(y->i);
    *(y->i) = temp;
}
3
Some programmer dude On

Lets take the swap_1 function:

void swap_1(E *x, E *y) {
    int *temp = NULL;
    temp = x->i;
    x->i = y->i;
    y->i = temp;
}

And draw each and every step to see what happens.

  • Lets begin with

    int *temp = NULL;
    

    and look at all the pointers you have and where they point, then it would look something like this:

    +------+
    | temp | --> NULL
    +------+
    
    +---+     +---+     +-------------+
    | x | --> | i | --> | a from main |
    +---+     +---+     +-------------+
    
    +---+     +---+     +-------------+
    | y | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    
  • Now lets do our first assignment:

    temp = x->i;
    

    And look and how it changes things:

    +------+
    | temp | ----------\
    +------+           |    +-------------+
                       >--> | a from main |
    +---+     +---+    |    +-------------+
    | x | --> | i | --/
    +---+     +---+ 
    
    +---+     +---+     +-------------+
    | y | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    

    As you can see you now have two pointers, both pointing to the same location (the a variable from the main function).

  • Now lets do the second assignment:

    x->i = y->i;
    

    Which will change things like this:

    +------+     +-------------+
    | temp | --> | a from main |
    +------+     +-------------+
    
    +---+     +---+
    | x | --> | i | --\ 
    +---+     +---+   |    +-------------+
                      >--> | b from main |
    +---+     +---+   |    +-------------+
    | y | --> | i | --/
    +---+     +---+
    

    Again you have two pointers both pointing to the same location (both x->i and y->i are pointing to the variable b from the main function).

  • And lastly the last assignment:

    y->i = temp;
    

    After this assignment the pointers will look like this:

    +---+     +---+     +-------------+
    | x | --> | i | --> | b from main |
    +---+     +---+     +-------------+
    
    +------+
    | temp | ----------\
    +------+           |    +-------------+
                       >--> | a from main |
    +---+     +---+    |    +-------------+
    | y | --> | i | --/
    +---+     +---+ 
    

From this it's clear that the swap_1 function doesn't swap the values of the a and b variables from the main function. Instead it swaps the pointers x->i and y->i. The values of a and b will still be the same.

To swap the actual values of a and b you need to dereference the pointers and use a plain non-pointer type for temp:

void swap_1(E *x, E *y)
{
    int temp = *x->i;  // Copy the value from where x->i points
    *x->i = *y->i;     // Copy the value
    *y->i = temp;      // Copy the value again
}

If you have problems with pointers in the future, using pencil and paper to draw and redraw variables and the pointers similar to the above usually helps visualize what's really happening. I suggest you try it yourself.