The unexpected ways to swap in C

PrimerPy
4 min readFeb 16, 2023

--

It’s been a while since I code in C. I remember how I struggled with the “bible”: C Programming Language when I was in college. I’m not sure it was a great choice as the first coding textbook for a college freshman who never coded before. I’ve never been a big fan of C ever since.

However I started to pick up C again recently and decided to give it another try as I grew interested in the embedded system and AIoT stuff. Today I encountered a very interesting challenge, how to swap two values in C. In Python or Javascript, this is so freaking simple

a, b= b, a

But in C, it’s a whole another story. I fired up my vi and type the following:

#include <stdio.h>

void swap(a, b){
int temp;
temp = a;
a = b;
b = temp;
}

int main(){
int a, b;
scanf("%d%d", &a, &b);
printf("before swap: a = %d, b = %d", a, b);
swap(a, b);
printf("after swap: a = %d, b = %d\n", a, b);

return 0
}

Unexpectedly, I failed as expected :) The results will be no swap, despite the introduction of temp!

Pointers

Then I recalled something painful about pointers, addresses, so here’s another try of rewriting the swap function

#include <stdio.h>

void swap(*a, *b){
int temp = *a;
*a = *b;
*b = temp;
}

int main(){
int a, b;
scanf("%d%d", &a, &b);
printf("before swap: a = %d, b = %d", a, b);
swap(&a, &b); // here we need to pass the addresses
printf("after swap: a = %d, b = %d\n", a, b);

return 0;
}

The output looks correct.

Macro

Yet, that’s not the end of the story. Defining a void swap function is fine, alternatively we could define and use a macro:

#include <stdio.h>
define swap(a,b){\
__typeof(a) __temp=a;\
a = b; b = __temp;\
}

int main(){
int a, b;
scanf("%d%d", &a, &b);
printf("a = %d, b = %d\n", a, b);
swap(a, b);
printf("swap: a = %d, b = %d\n", a, b);
return 0;
}

The macro provided uses the __typeof keyword to declare a variable __temp with the same type as a. This ensures that the temporary variable used in the swap operation has the correct type.

XOR

Finally we can use the XOR swap algorithm to swap two integer values without using a temporary variable:

#include <stdio.h>

int main() {
int a, b;

printf("Enter two integer values to swap: ");
scanf("%d %d", &a, &b);

printf("Before swap: a = %d, b = %d\n", a, b);

a = a ^ b;
b = a ^ b;
a = a ^ b;

printf("After swap: a = %d, b = %d\n", a, b);

return 0;
}

The XOR swap algorithm works by taking advantage of the properties of the bitwise exclusive or (XOR) operator. When you XOR two values together, the result will be a new value that has the bits set to 1 wherever the corresponding bits in the original values differed.

So, to swap two values a and b using the XOR swap algorithm, we perform the following three operations:

  1. Set a to a ^ b, which sets a to the XOR of its original value and b.
  2. Set b to a ^ b again, which sets b to the XOR of the new value of a and its original value, effectively setting b to the original value of a.
  3. Set a to a ^ b again, which sets a to the XOR of its new value and b, which is now equal to the original value of a, effectively setting a to the original value of b.

Pretty cool, right?

Which is better?

The function approach is a runtime operation and incurs a function call overhead. However, modern compilers can often inline small functions like the swap function we defined earlier, which can eliminate the function call overhead. The function approach is more flexible than the macro approach since it can handle different types of arguments being swapped.

The macro approach is a compile-time operation and does not incur any function call overhead. The code generated by the macro approach is often inlined by the compiler, which can result in efficient code. However, the macro approach requires that the types of the arguments being swapped are compatible, and it may not work correctly in all cases.

The XOR approach is a bitwise operation that can be faster than the macro or function approach on some architectures. The XOR approach avoids the need for a temporary variable by using bitwise XOR operations. However, the XOR approach requires that the values being swapped are of the same type and may not work correctly in all cases. Additionally, the XOR approach can be less readable than the macro or function approach.

--

--

PrimerPy
PrimerPy

Written by PrimerPy

www.primerpy.com | A Primer on Python. I'm a veteran Data and Web developer based out of NYC and DC area. I blog mainly on Python and other tech related topics.