18 Jo P June 08


Published on

Published in: Technology, News & Politics
  • Be the first to comment

  • Be the first to like this

18 Jo P June 08

  1. 1. The Joy of Programming S.G. GaneSh Traps and Pitfalls: Swapping Two Variables—Part III In May and June last year, we covered a few traps and pitfalls in trying to swap two variables without using a temporary. This month, we’ll look at swapping variables without a temporary in a single statement, and see how C and Java compilers treat them differently. T he following trick using three consecutive ex-or public static void main(String []s) { operations for swapping two variables without int i = 3, j = 6; using a temporary is well known and particularly System.out.println(“Before swap: i = “ + i + “ j = “ + j); popular among students: i ^= (j ^= (i ^= j)); System.out.println(“After swap: i = “ + i + “ j = “ + j); i ^= j; j ^= i; i ^= j; } } Here, i and j are integer variables and it works well (we covered a few pitfalls earlier with this). For further The swap trick does not work! What happened? The optimisation, one often sees this solution combining the Java specification (section 15.26.2) says: “The value of three statements into a single statement: the left-hand side of a compound assignment is saved before the right-hand side is evaluated”. In other words, i ^= (j ^= (i ^= j)); the value of i and j are remembered and used for the LHS values of i and j; so we do not get the values of i and Try this with your favourite C compiler; it usually j swapped correctly. works. This trick works based on the following To illustrate this, let us try the following: Pre- assumption: the values of i and j are modified in the RHS compute the result of (i ^ j) and remember it in a (right-hand side) of the expression and the modified temporary. Now use that temporary in the LHS instead values are expected to be used in the LHS (left-hand side) of i; you’ll get the expected (correct) output of the of the expression. swapped values of two variables: However, this solution need not work and the updated values of i and j need not get reflected when read class SwapTest { again. This is because the compiler is free to optimise public static void main(String []s) { the sequence of reads and writes, using temporaries int i = 3, j = 6; internally. This problem is covered by an intricate and int cache = (i ^ j); difficult to understand technical issue known as ‘sequence System.out.println(“Before swap: i = “ + i + “ j = “ + j); points’ (see en.wikipedia.org/wiki/Sequence_point). For cache ^= (j ^= (i ^= j)); example, if the initial value of i is 0, after executing the i = cache; statement i=i++, i might be 0 or 1: it is implementation System.out.println(“After swap: i = “ + i + “ j = “ + j); defined behaviour. For the same reason, the expression i } ^= (j ^= (i ^= j)) need not swap the two variables i and j } correctly—it depends on the compiler as to what we’ll get as values for i and j. It works, right? We’ll take a different approach in this column Well, don’t worry if you feel that the explanation for the and cover Java to understand the implications of Java programs is not clear. Next month, we’ll dig deeper by such statements. Unlike C, Java does not have code looking at the byte codes generated for the swap code and segments leading to implementation defined behaviour understand how it works. (i.e., the programs written in Java will behave the same way, irrespective of the Java compiler used). For S.G. Ganesh is a research engineer in Siemens (Corporate the swap in a single statement case, let us see what Technology), Bangalore. His latest book is “60 Tips on happens in Java: Object Oriented Programming” (ISBN 978-0-07-065670-3), published by Tata McGraw-Hill, New Delhi. You can reach class Swap { him at sgganesh@gmail.com 102 june 2008 | LInuX For You | www.openITis.com