You are just swapping the local copies of your pointers, not the things the pointer point to, as you forgot to dereference your pointers. Also, your temp value holds a pointer too, which doesn't make sense - it should hold one of the values you are swapping.
Instead of this...
int *temp;
temp = a;
a = b;
b = temp;
...you need this:
int temp;
temp = *a;
*a = *b;
*b = temp;
For better understanding, let's explain this with an analogy.
Suppose your memory is a cabinet full of drawers. Each draw is labelled with some letter (its address), and in the drawers, there are pieces of paper with other numbers or letters written on them (the values stored at each address). In this explanation I use letters as addresses even though in reality, addresses are numbers as well.
Now let's see what happens in your original code. To simplify the explanation, I will inline the function.
This is what we have then:
int a = 78;
int b = 98;
int *c = &a;
int *d = &b;
int *temp = c;
c = d;
d = temp;
And this is what it does:
// Let's put a note with `78` written on it into drawer `A`.
int a = 78;
// Now we have: A="78"
// Let's put a note with `98` written on it into drawer `B`.
int b = 98;
// Now we have: A="78", B="98"
// Let's put a note with `A` written on it into drawer `C`.
int *c = &a;
// Now we have: A="78", B="98", C="A"
// Let's put a note with `B` written on it into drawer `D`.
int *d = &b;
// Now we have: A="78", B="98", C="A", D="B"
// Let's check the note in drawer `C` (which currently says `A`)
// and put a similar note into drawer `T`.
int *temp = c;
// Now we have: A="78", B="98", C="A", D="B", T="A"
// Let's check the note in drawer `D` (which currently says `B`)
// and put a similar note into drawer `C` (discarding what is
// already there).
c = d;
// Now we have: A="78", B="98", C="B", D="B", T="A"
// Let's check the note in drawer `T` (which currently says `A`)
// and put a similar note into drawer `D` (discarding what is
// already there).
d = temp;
// Now we have A="78", B="98", C="B", D="A", T="A"
If you look at the final result, you will see that the contents of the drawers A
and B
never changed. We just fiddled around a bit with our drawers C
, D
and T
.
Now let's look at the working solution, again inlined for simplicity:
int a = 78;
int b = 98;
int *c = &a;
int *d = &b;
int temp = *c;
*c = *d;
*d = temp;
And see how it works now:
// Let's put a note with `78` written on it into drawer `A`.
int a = 78;
// Now we have: A="78"
// Let's put a note with `98` written on it into drawer `B`.
int b = 98;
// Now we have: A="78", B="98"
// Let's put a note with `A` written on it into drawer `C`.
int *c = &a;
// Now we have: A="78", B="98", C="A"
// Let's put a note with `B` written on it into drawer `D`.
int *d = &b;
// Now we have: A="78", B="98", C="A", D="B"
// ==== SO FAR SO GOOD, NOW LET'S SEE WHAT IS DIFFERENT THIS TIME ===
// Let's check the note in drawer `C` (which currently says `A`).
// Then LOOK INTO ANOTHER DRAWER according to the note we just found
// (which said `A`), look at the note in there (which currently says
// `78`) and put a similar note into drawer `T`.
int temp = *c;
// Now we have: A="78", B="98", C="A", D="B", T="78"
// Let's check the note in drawer `D` (which currently says `B`).
// Then LOOK INTO ANOTHER DRAWER according to the note we just found
// (which said `B`), look at the note in there (which currently says
// `98`) and prepare a similar note.
// Then check the note in drawer `T` (which currently says `A`).
// Then OPEN ANOTHER DRAWER according to the second note we just found
// (which said `A`), and put the copied note that we got before
// (which said `98`) into that drawer.
*c = *d;
// Now we have: A="98", B="98", C="A", D="B", T="78"
// Let's check the note in drawer `T` (which currently says `78`)
// and prepare a similar note.
// Then check the note in drawer `D` (which currently says `B`).
// Then OPEN ANOTHER DRAWER according to the second note we just found
// (which said `B`), and put the copied note that we got before
// (which said `78`) into that drawer.
*d = temp;
// Now we have A="98", B="78", C="A", D="B", T="78"
The difference is that this time we use C
and D
only to store a "pointer" to A
and B
, and not directly any numbers, so we always looked into C
or D
to find another drawer's letter in there and then continue accessing that drawer, so we ended up actually swapping the numbers in A
and B
as we wanted.
You may say, "why did we even have to use extra drawers C
and D
then?", and you would be right - but only because this example inlined the function call. If you call a function, you have to pass some "notes" (arguments) to it which it will put in its own drawers (argument variables) - you can't pass whole drawers (i.e. values by reference). So instead of being able to pass the drawers A
and B
directly, you do the next best thing and pass two notes with A
and B
written on them - your pointers - which the function will put into its own drawers C
and D
at that point. The function can then check what's written on these notes to know which actual drawers (with your numbers in them) you wanted the function to operate on.
By the way, C is pass-by-value, not pass-by-reference. C++ can be both because it has a reference type, but C doesn't. All you can do is use pointers, but then you are technically still passing a pointer by value, although logically speaking, you can view the pointer as reference to some value so you could say you are passing that value by reference, even though syntactically you aren't.
For comparison, in C++ you could do this:
// The & here is *not* related to pointers but means
// "pass this argument by reference", essentially
void swap (int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
// ...
int a = 123;
int b = 456;
swap(a, b);
In terms of the analogy above, this would be equivalent to passing the whole drawers A
and B
to the function so that the function can temporarily put them into its own cabinet and swap the notes inside of them, instead of passing notes with the labels of your own drawers.