1. The Joy of
Programming
C Traps and Pitfalls:
Swapping Two Variables S.G. GANESH
Let us look at the interesting problem of swapping two variables without using any temporary
variables. We will discover the possible pitfalls of using smart ‘tricks’ to solve the problem. This
column is to help students and novices understand C better.
I
t is assumed that the underlying machine follows 2’s void swap(float *i, float *j){
complement representation for integers and IEEE 754 *i = *i + *j;
floating point standard for floating point numbers. *j = *i - *j;
Let us look at a well-known trick of swapping two integers *i = *i - *j;
without using any temporary variables, which uses arithmetic }
operators + and -:
float i = FLT_MAX;
void swap(int *i, int *j){ float j = FLT_MAX;
*i = *i + *j; printf(“Before swap : %f %fn”, i, j);
*j = *i - *j; swap(&i, &j);
*i = *i - *j; printf(“After swap : %f %f n”, i, j);
} // prints
// Before swap : 340282346638528860000000000000000000000.000000
Yes, we know it works. But does it really work in all cases? 340282346638528860000000000000000000000.000000
How about this code: // After swap : -1.#INF00 1.#INF00
GUEST COLUMN
int arr[5] = {10,20,30,40,50}; Also, even for ordinary values, performing arithmetic
int *ip = &arr[3]; operations can result in a loss of precision; so the swapped
swap(ip,&arr[3]); values need not be exactly the same:
for(int i = 0; i<5; i++)
printf(“%d “, arr[i]); float i = 12345678.9f, p = i;
// output: 10 20 30 0 50 float j = 98765432.1f, q = j;
assert((i == p) && (j == q));
So, when the elements to be swapped happen to refer swap(&i, &j);
to the same location, swapping fails. In the statement ‘*i= assert((i == q) && (j == p));
*i + *j;’, the implicit assumption is that *i and *j point to
two different locations; this trick will not work if the // Assertion failed: (i == q) && (j == p), file E:tem.c, line 14
results of + and – operations are over-written. Here is a // abnormal program termination
small test case just to demonstrate that:
You can reasonably expect that the assertion will fail in this
int x = 10; manner for many floating point numbers because arithmetic
printf(“before calling swap, x = %d n”, x); operations with floats can result in some precision loss. But it
swap (&x, &x); won’t fail for any of the integral values, as there is no possible
printf(“after calling swap, x = %d”, x); precision loss for any integral arithmetic operations.
// prints: before calling swap, x = 10 Another popular trick among students is to swap two
// after calling swap, x = 0 variables using three repeated ex-or operations. Well, this
solution also has many traps and pitfalls, and we’ll discuss
There are other problems with this swap solution them in the next column.
for integers, but for now, we’ll see if we can use this trick for
swapping two floating point numbers.
This solution doesn’t work for floats because the operation S.G. Ganesh is an engineer in Hewlett-Packard’s C++
‘*i + *j’ might overflow. For integers, overflow can be compiler team. He has authored a book “Deep C” (ISBN 81-
expected to result in rotation of values and it will work fine in 7656-501-6). He is also a member of the ANSI/ISO C++
Standardisation committee (JTC1/SC22/WG21), representing
practice (try it!); it’s not the case with floating point overflow.
HP. You can reach him at sgganesh@gmail.com.
The following program shows this:
www.linuxforu.com | LINUX FOR YOU | MAY 2007 73
CMYK