Why does this work well?
It does not work well.
It seems to work well because you lie to your compiler and use insufficient test data.
void swapString(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
You claim to provide a pointer to a pointer. As a consequence this functions swaps as much bytes between two places as a pointer takes. That is 4 or 8 bytes on most systems.
But then you pass addresses of arrays, not pointers to pointers:
char strings[][30] = {"Test1","Test2","Test3"};
swapString((char **)&strings[0],(char **)&strings[1]);
This is causing undefined behaviour. You are using casts because your compiler told you that this is crab if you remove them:
test.c:15:28: warning: passing argument 2 of ‘swapString’ from incompatible pointer type [-Wincompatible-pointer-types]
15 | swapString(&strings[0],&strings[1]);
| ^~~~~~~~~~~
| |
| char (*)[30]
test.c:3:41: note: expected ‘char **’ but argument is of type ‘char (*)[30]’
As a result the function thinks it swaps a pointer but instead it swaps the first 8 bytes of your array.
To verify this you could use longer strings:
#include <stdio.h>
void swapString(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
int main()
{
char strings[][30] = {"Test111111","Test222222","Test333333"};
int i;
swapString((char **)&strings[0],(char **)&strings[1]);
for(i=0;i<3;i++){
printf("%s\n",strings[i]);
}
return 0;
}
And then you get the result you deserve. ;)
Test$ ./test
Test222211
Test111122
Test333333
In case of 32bit addresses you need to make the first 4 bytes of your strings distinguishable.
As you can see, there are no swapped pointers at all. Just the start of your arrays is messed up.
If you want to swap strings by just swapping pointers, you need to change your array definition:
char *strings[] = {"Test111111","Test222222","Test333333"};
swapString(&strings[0],&strings[1]);
As a side effect you can also drop the casts from your function call as the types now match what is expected.
const. The biggest risk is that your function assumes it can just change the pointers, while in reality the pointers are put in some read-only section. That's up to the developer to keep track of, and properly applyconstspecifiers.