I have been struggling to understand the different behaviour when swapping pointers in C. If I want to swap two int
pointers, then I can do
void intSwap (int *pa, int *pb){ int temp = *pa; *pa = *pb; *pb = temp; }
However, if I want to swap two char
pointers I need to do something like
void charSwap(char** a, char** b){ char *temp = *a; *a = *b; *b = temp; }
because if I do
void charSwap(char* a, char* b){ char temp = *a; *a = *b; *b = temp; }
the compiler complains about the expression *a = *b as it cannot change the values. If I want to swap two strings
(i.e. char* s1= "Hello"; char* s2="Bye";
)how would one do it?
Could you please give me a little bit of help? I would like to really learn how it works so I will not need to experience trial and error all the time until I get the right answer. I hope it's useful for many other people.
Using pointers. If we pass pointers to our variables into the function, the function can swap the values in our variables, instead of its own argument copies. void swap2(int* a, int* b) { int temp = *a; *a = *b; *b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! }
Swapping two void pointers is easy without using any extra memory: void* p1; void* p2; //... p1 = ((uintptr_t)p1) ^ ((uintptr_t)p2); p2 = ((uintptr_t)p1) ^ ((uintptr_t)p2); p1 = ((uintptr_t)p1) ^ ((uintptr_t)p2);
The first thing you need to understand is that when you pass something to a function, that something is copied to the function's arguments.
Suppose you have the following:
void swap1(int a, int b) { int temp = a; a = b; b = temp; assert(a == 17); assert(b == 42); // they're swapped! } int x = 42; int y = 17; swap1(x, y); assert(x == 42); assert(y == 17); // no, they're not swapped!
The original variables will not be swapped, because their values are copied into the function's arguments. The function then proceeds to swap the values of those arguments, and then returns. The original values are not changed, because the function only swaps its own private copies.
Now how do we work around this? The function needs a way to refer to the original variables, not copies of their values. How can we refer to other variables in C? Using pointers.
If we pass pointers to our variables into the function, the function can swap the values in our variables, instead of its own argument copies.
void swap2(int* a, int* b) { int temp = *a; *a = *b; *b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } int x = 42; int y = 17; swap2(&x, &y); // give the function pointers to our variables assert(x == 17); assert(y == 42); // yes, they're swapped!
Notice how inside the function we're not assigning to the pointers, but assigning to what they point to. And the pointers point to our variables x
and y
. The function is changing directly the values stored in our variables through the pointers we give it. And that's exactly what we needed.
Now what happens if we have two pointer variables and want to swap the pointers themselves (as opposed to the values they point to)? If we pass pointers, the pointers will simply be copied (not the values they point to) to the arguments.
void swap3(int* a, int* b) { int* temp = a; a = b; b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } void swap4(int* a, int* b) { int temp = *a; *a = *b; *b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } int x = 42; int y = 17; int* xp = &x; int* yp = &y; swap3(xp, yp); assert(xp == &x); assert(yp == &y); assert(x == 42); assert(y == 17); // Didn't swap anything! swap4(xp, yp); assert(xp == &x); assert(yp == &y); assert(x == 17); assert(y == 42); // Swapped the stored values instead!
The function swap3
only swaps its own private copies of our pointers that it gets in its arguments. It's the same issue we had with swap1
. And swap4
is changing the values our variables point to, not the pointers! We're giving the function a means to refer to the variables x
and y
but we want them to refer to xp
and yp
.
How do we do that? We pass it their addresses!
void swap5(int** a, int** b) { int* temp = *a; *a = *b; *b = temp; assert(**a == 17); assert(**b == 42); // they're swapped! } int x = 42; int y = 17; int* xp = &x; int* yp = &y; swap5(&xp, &yp); assert(xp == &y); assert(yp == &x); assert(x == 42); assert(y == 17); // swapped only the pointers variables
This way it swaps our pointer variables (notice how xp
now points to y
) but not the values they point to. We gave it a way to refer to our pointer variables, so it can change them!
By now it should be easy to understand how to swap two strings in the form of char*
variables. The swap function needs to receive pointers to char*
.
void swapStrings(char** a, char** b){ char *temp = *a; *a = *b; *b = temp; assert(strcmp(*a, "world") == 0); assert(strcmp(*b, "Hello") == 0); } char* x = "Hello"; char* y = "world"; swapStrings(&x, &y); assert(strcmp(x, "world") == 0); assert(strcmp(y, "Hello") == 0);
void intSwap (int *pa, int *pb){ int temp = *pa; *pa = *pb; *pb = temp; }
You need to know the following -
int a = 5; // an integer, contains value int *p; // an integer pointer, contains address p = &a; // &a means address of a a = *p; // *p means value stored in that address, here 5
void charSwap(char* a, char* b){ char temp = *a; *a = *b; *b = temp; }
So, when you swap like this. Only the value will be swapped. So, for a char*
only their first char
will swap.
Now, if you understand char* (string) clearly, then you should know that, you only need to exchange the pointer. It'll be easier to understand if you think it as an array
instead of string.
void stringSwap(char** a, char** b){ char *temp = *a; *a = *b; *b = temp; }
So, here you are passing double pointer because starting of an array
itself is a pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With