Procedure to swap values

Feb 4, 2009 at 4:28am
I need to write a procedure that swaps the values of a and b if a is greater and otherwise leaves a and b unchanged.

Here is what I have so far:

#include<iostream>


using namespace std;

void sort(int &a, int &b)
{
if (a > b)
int temp = a;
a = b;
b = temp;
}

int main()
{
int u = 2;
int v = 3;
sort(u, v);
cout << "u=" << u << "v=" << v << endl;

system("pause");
return 0;
}

I keep getting an error message that temp is undeclared in the line "b = temp". Any idea why?
Feb 4, 2009 at 4:32am
put the condition of (a > b) in main rather than in swap(). Also I dont know why do you have references passed as parameters to the swap function. Just pass the values. This way only if your condition of (a>b) if satisfied in main, the control will go in the function swap( ).
Feb 4, 2009 at 4:41am
An if statement will only execute 1 statement if the condition is true, unless you specify a block of statements using {}'s.

The pass by reference is fine, it will do exactly what you want once you add {}'s.

This is equivalent to your function at this point:
1
2
3
4
5
6
7
8
9
void sort(int &a, int &b)
{
    if (a > b)
    {
        int temp = a;
    }
    a = b;
    b = temp;
}


Once the block ends, temp goes out of scope. This is what the error message is telling you.
Last edited on Feb 4, 2009 at 4:42am
Feb 4, 2009 at 4:55am
Thank you seymore. Knew it was something simple I was overlooking...
Feb 4, 2009 at 5:17am
It always is. Glad to help out.
Feb 4, 2009 at 7:07pm
Quicker way :) Without the use of a temp variable
1
2
3
4
5
6
7
void sort(int &a, int &b) {
 if (a > b) {
   a = a + b;
   b = a - b;
   a = a - b;
 }
}
Feb 4, 2009 at 7:34pm
Now that's clever; I have never seen that before! Nice post Zaita.
Feb 4, 2009 at 7:56pm
That is very similar to the xor method.
Feb 5, 2009 at 3:27am
How about to sort three variables in descending order? Would you need multiple if statements?

i.e.:

int temp = 0;

if (a > b)
{
temp = a;
a = b;
b = temp;
}

if (b > c)
{
temp = b;
b = c;
c = temp;
}
if (a > b)
{
temp = a;
a = b;
b = temp;
}
Last edited on Feb 5, 2009 at 3:50am
Feb 5, 2009 at 8:55am
This works just fine, but if you want to sort more numbers, you're gonna have to type a lot of if-statements. With n numbers there are n*(n-1)/2. So you should think about putting the numbers in an array and using a for-loop.

By the way. This kind of sorting is called bubble-sort.
http://en.wikipedia.org/wiki/Bubble_sort
Feb 5, 2009 at 11:07pm
Ah, the Bubble Sort. I remember this.

Thanks mordekai.
Feb 6, 2009 at 3:42am
Zaita,

Your way without the temp variable wouldn't work here, huh?

http://www.cplusplus.com/reference/string/swap.html
Feb 6, 2009 at 5:49am
I'd bet the STL is implemented using the temp variable approach so that it only requires the value_type to be Assignable. The solution posted would additionally require that the operators + and - be defined. It would work for integral types; maybe there should be a template specialization for that (actually, for all I know there might already be one).
Feb 6, 2009 at 6:08am
Zaita's method works only with numerical types (integers, floats, bignums, etc.).
But I kinda like the XOR version better, even if it only with integers:
1
2
3
a^=b;
b^=a;
a^=b;


The standard swap is just
1
2
3
4
5
6
template <typename T>
void swap(T &a,T &b){
    T temp=a;
    a=b;
    b=temp;
}

I doubt there's a template specialization.
Last edited on Feb 6, 2009 at 6:11am
Feb 6, 2009 at 1:02pm
No because the add/sub trick and the xor trick are both slower than using a temporary. They'd only specialize to optimize.
Feb 6, 2009 at 5:11pm
Really? It's slower? Even though in the past, people would zero by XORing something to itself?
Feb 6, 2009 at 5:50pm
Wikipedia says that most compilers can optimize away the temporary but the XOR swap must always be sequential and would not be optimized. Interesting!
Feb 6, 2009 at 5:59pm
I suppose the temp variable method might well be faster:

In the interest of scientific research:
Here is the source:
1
2
3
4
5
6
7
  temp = a;
  a=b;
  b=temp;

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


and here is the resultant code:

1
2
3
4
5
6
7
8
9
10
11
12
    19:   temp = a;
004114EC 8B 45 F8         mov         eax,dword ptr [a] 
004114EF 89 45 E0         mov         dword ptr [temp],eax 
    20:   a=b;
004114F2 8B 45 EC         mov         eax,dword ptr [b] 
004114F5 89 45 F8         mov         dword ptr [a],eax 
    21:   b=temp;
004114F8 8B 45 E0         mov         eax,dword ptr [temp] 
004114FB 89 45 EC         mov         dword ptr [b],eax 
    22:
    23:   a^=b;
004114FE 8B 45 F8         mov         eax,dword ptr [a] 
00411501 33 45 EC         xor         eax,dword ptr [b] 
00411504 89 45 F8         mov         dword ptr [a],eax 
    24:   b^=a;
00411507 8B 45 EC         mov         eax,dword ptr [b] 
0041150A 33 45 F8         xor         eax,dword ptr [a] 
0041150D 89 45 EC         mov         dword ptr [b],eax 
    25:   a^=b;
00411510 8B 45 F8         mov         eax,dword ptr [a] 
00411513 33 45 EC         xor         eax,dword ptr [b] 
00411516 89 45 F8         mov         dword ptr [a],eax 


*MSVC*
Feb 6, 2009 at 7:03pm
guestgulkan: Could you try optimized?
Feb 6, 2009 at 7:34pm
Fascinating. I've no fear:

g++ -O6 foo.cpp -S

on the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

inline void swap1( int& a, int& b ) {
    a ^= b;
    b ^= a;
    a ^= b;
}

inline void swap2( int& a, int& b ) {
   int temp = a;
   a = b;
   b = temp;
}

int main() {
    int x = rand(), y = rand();
    swap1( x, y );
    printf( "%d %d", x, y );
    swap2( x, y );
    printf( "%d %d", x, y );
}


Both algorithms generated the exact same code, which is to say... none.

The compiler seems to recognize the swap algorithm because the assembler it generated was to store x in %esi and y in %ebx, and then it just pushed the two parameters onto the stack for the call to printf() in swapped order in both cases.


EDIT: now if I remove the keyword "inline" then the compiler actually generates function calls, and my results largely concur with guestgulkan's even at O6: the assembler shows 8 memory accesses in the XOR case (5 moves and 3 xors) and 6 in the temporary case (all moves).

Last edited on Feb 6, 2009 at 7:36pm
Topic archived. No new replies allowed.