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
CodePudding user response:
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;
}
CodePudding user response:
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
avariable from themainfunction).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->iandy->iare pointing to the variablebfrom themainfunction).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.
