[c] Swapping pointers in C (char, int)

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.

This question is related to c pointers

The answer is


You need to understand the different between pass-by-reference and pass-by-value.

Basically, C only support pass-by-value. So you can't reference a variable directly when pass it to a function. If you want to change the variable out a function, which the swap do, you need to use pass-by-reference. To implement pass-by-reference in C, need to use pointer, which can dereference to the value.

The function:

void intSwap(int* a, int* b)

It pass two pointers value to intSwap, and in the function, you swap the values which a/b pointed to, but not the pointer itself. That's why R. Martinho & Dan Fego said it swap two integers, not pointers.

For chars, I think you mean string, are more complicate. String in C is implement as a chars array, which referenced by a char*, a pointer, as the string value. And if you want to pass a char* by pass-by-reference, you need to use the ponter of char*, so you get char**.

Maybe the code below more clearly:

typedef char* str;
void strSwap(str* a, str* b);

The syntax swap(int& a, int& b) is C++, which mean pass-by-reference directly. Maybe some C compiler implement too.

Hope I make it more clearly, not comfuse.


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.


In C, a string, as you know, is a character pointer (char *). If you want to swap two strings, you're swapping two char pointers, i.e. just two addresses. In order to do any swap in a function, you need to give it the addresses of the two things you're swapping. So in the case of swapping two pointers, you need a pointer to a pointer. Much like to swap an int, you just need a pointer to an int.

The reason your last code snippet doesn't work is because you're expecting it to swap two char pointers -- it's actually written to swap two characters!

Edit: In your example above, you're trying to swap two int pointers incorrectly, as R. Martinho Fernandes points out. That will swap the two ints, if you had:

int a, b;
intSwap(&a, &b);

This example does not swap two int pointers. It swaps the value of the integers that pa and pb are pointing to. Here's an example of what's going on when you call this:

void Swap1 (int *pa, int *pb){
    int temp = *pa;
    *pa = *pb;
    *pb = temp;
}
int main()
{
    int a = 42;
    int b = 17;


    int *pa = &a;
    int *pb = &b;

    printf("--------Swap1---------\n");
    printf("a = %d\n b = %d\n", a, b);
    swap1(pa, pb);
    printf("a = %d\n = %d\n", a, a);
    printf("pb address =  %p\n", pa);
    printf("pa address =  %p\n", pb);
}

The output here is:

a = 42
b = 17
pa address =  0x7fffdf933228
pb address =  0x7fffdf93322c
--------Swap---------
pa = 17
pb = 42
a = 17
b = 42
pa address =  0x7fffdf933228
pb address =  0x7fffdf93322c

Note that the values swapped, but the pointer's addresses did not swap!

In order to swap addresses we need to do this:

void swap2 (int **pa, int **pb){
    int temp = *pa;
    *pa = *pb;
    *pb = temp;
}

and in main call the function like swap2(&pa, &pb);

Now the addresses are swapped, as well as the values for the pointers. a and b have the same values that the are initialized with The integers a and b did not swap because it swap2 swaps the addresses being being pointed to by the pointers!:

a = 42
b = 17
pa address =  0x7fffddaa9c98
pb address =  0x7fffddaa9c9c
--------Swap---------
pa = 17
pb = 42
a = 42
b = 17
pa address =  0x7fffddaa9c9c
pb address =  0x7fffddaa9c98

Since Strings in C are char pointers, and you want to swap Strings, you are really swapping a char pointer. As in the examples with an int, you need a double pointer to swap addresses.

The values of integers can be swapped even if the address isn't, but Strings are by definition a character pointer. You could swap one char with single pointers as the parameter, but a character pointer needs to be a double pointer in order to swap the strings.


If you have the luxury of working in C++, use this:

template<typename T>
void swapPrimitives(T& a, T& b)
{
    T c = a;
    a = b;
    b = c;
}

Granted, in the case of char*, it would only swap the pointers themselves, not the data they point to, but in most cases, that is OK, right?