# swaping numbers

• 03-29-2004
bj31t
swaping numbers
I am trying to put three numbers in order from smallest to largest by swaping them. I can figure out how to get all of them to display after they are swapped. Any help would be great.
Code:

```void swap2(double a, double b) {                double temp = a;         a = b;         b = temp; } int main() {         double a, b, c;                cout<<"Enter three numbers.";                                                        cout<<endl;                                        cin>>a >>b >>c;                                        cout<<endl;                                                if (a < b && a < c)                                                {                                         cout<<a;                cout<<endl;                                                                }         else if (b < c)         {                 cout<<b;                 cout<<endl;         }                 else         {                 swap2(b,c);                 cout<<c                 cout<<endl;                 cout<<b;                 cout<<endl;         } return 0; }```
• 03-29-2004
Hammer
>>void swap2(double a, double b)
You need to pass the address of the variable in order to perform the swap. All you're currrently doing is swapping the values around in local variables, leaving those in main() as they were.

Code:

```void swap2(double *a, double *b) {   double  temp = *a;   *a = *b;   *b = temp; } swap2(&b, &c);```
You'll also need to store your input in an array if you want to make things more efficient.

Try looking up the bubble sort on google
It's pretty inefficient, but it's a good sorting routine to learn as a beginner.

When your ready, take a look at Prelude's Corner for more detailed stuff
http://faq.cprogramming.com/cgi-bin/...&id=1073086407
• 03-29-2004
Prelude
References would be better. :)
Code:

```void swap3(double& a, double& b) {   double  temp = a;   a = b;   b = temp; } swap3(b, c);```
• 03-29-2004
bj31t
Prelude, could you explain what you mean. I dont understand.
Thanks
• 03-29-2004
Prelude
>Prelude, could you explain what you mean.
A reference is a (potentially) different name for the same object. Instead of passing a pointer to the address of the object as Hammer showed you, passing a reference gives you simpler syntax. You pass b and c without having to worry about passing an address, then swap a and b without having to worry about dereferencing.

A good C++ book will give you more detail than I can in a short post.
• 03-29-2004
JaWiB
Just wondering...
Code:

```template <typename T> void swap (T& a, T& b) { a^=b^=a^=b; }```
Is there any disadvantage to that? (Or is there any real advantage to it?)
• 03-29-2004
Codeplug
- only works on integral types of T
- will most likely confuse the average reader of the code
- there's no real speed gain on modern CPU's

- cool to look at
- will most likely confuse the average reader of the code

gg
• 03-29-2004
JaWiB
Quote:

Originally Posted by Codeplug
...
- will most likely confuse the average reader of the code
...

...
- will most likely confuse the average reader of the code

gg

Rofl :D .
• 03-29-2004
Prelude
>Is there any disadvantage to that?
The most obvious (or maybe not judging from how often I see the construct) is that it modifies an object more than once between sequence points and is thus undefined. Assuming it works correctly then if a and b both refer to the same variable unexpected things will happen if you aren't prepared for them.
• 03-29-2004
Codeplug
>> it modifies an object more than once between sequence points and is thus undefined

I'm gonna argue :)
Quote:

From ISO/IEC FDIS 14882 (Final Draft)
1.9-7 Accessing an object designated by a volatile lvalue (basic.lval), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression might produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place.
Even though there are multiple assignments within a single sequence point, I would argue that the statement is still well defined due to the left to right associativity of the xor-equals operator.

Quote:

From ISO/IEC FDIS 14882 (Final Draft)
1.9-15 [Note: operators can be regrouped according to the usual mathematical rules only where the operators really are associative or commutative.*
[Footnote: Overloaded operators are never assumed to be associative or commutative. --- end foonote]
For example, in the following fragment
int a, b;
/*...*/
a = a + 32760 + b + 5;
the expression statement behaves exactly the same as
a = (((a + 32760) + b) + 5);
due to the associativity and precedence of these operators. Thus, the result of the sum (a + 32760) is next added to b, and that result is then added to 5 which results in the value assigned to a. On a machine in which overflows produce an exception and in which the range of values representable by an int is [-32768,+32767], the implementation cannot rewrite this expression as
a = ((a + b) + 32765);
since if the values for a and b were, respectively, -32754 and -15, the sum a + b would produce an exception while the original expression would not; nor can the expression be rewritten either as
a = ((a + 32765) + b);
or
a = (a + (b + 32765));
since the values for a and b might have been, respectively, 4 and -8 or -17 and 12. However on a machine in which overflows do not produce an exception and in which the results of overflows are reversible, the above expression statement can be rewritten by the implementation in any of the above ways because the same result will occur. ]
As section 1.9-15 describes, compilers are only allowed to regroup mathematically associative or commutative operators of equal precedence if doing so gives the same results as not regrouping the operators.

So my assertion is that the "^=" operator is not associative or commutative, so the compiler must adhere to the left-to-right associativity of the xor-equals operator. And thus, is equivalent to the following:
Code:

```a ^= b; b ^= a; a ^= b;```
[atleast that's my humble interpretation of things]

gg
• 03-30-2004
laserlight
hmm... but speedwise shouldnt assignment be faster than mathematical calculations, even if it is 3 simple XORs?

though it doesnt really matter, I suppose :)
• 03-30-2004
Codeplug
Hmmmm, lets see
Code:

```void s1(int &a, int &b) {     a ^= b ^= a ^= b; } void s2(int &a, int &b) {     int t = a;     a = b;     b = t; }```
Code:

```PUBLIC  ?s1@@YAXAAH0@Z                  ; s1 _TEXT  SEGMENT _a\$ = 8 _b\$ = 12 ?s1@@YAXAAH0@Z PROC NEAR                ; s1, COMDAT ; 13  :    a ^= b ^= a ^= b;     mov ecx, DWORD PTR _b\$[esp-4]     mov eax, DWORD PTR _a\$[esp-4]     push    esi     mov edx, DWORD PTR [ecx]     mov esi, DWORD PTR [eax]     xor esi, edx     mov DWORD PTR [eax], esi     mov edx, esi     mov esi, DWORD PTR [ecx]     xor esi, edx     mov DWORD PTR [ecx], esi     mov edx, DWORD PTR [eax]     mov ecx, esi     pop esi     xor edx, ecx     mov DWORD PTR [eax], edx ; 14  : }     ret 0 ?s1@@YAXAAH0@Z ENDP                ; s1 PUBLIC  ?s2@@YAXAAH0@Z                  ; s2 _TEXT  SEGMENT _a\$ = 8 _b\$ = 12 ?s2@@YAXAAH0@Z PROC NEAR                ; s2, COMDAT ; 18  :    int t = a; ; 19  :    a = b;     mov edx, DWORD PTR _b\$[esp-4]     mov eax, DWORD PTR _a\$[esp-4]     push    esi     mov esi, DWORD PTR [edx]     mov ecx, DWORD PTR [eax]     mov DWORD PTR [eax], esi ; 20  :    b = t;     mov DWORD PTR [edx], ecx     pop esi ; 21  : }     ret 0 ?s2@@YAXAAH0@Z ENDP                ; s2```
Looks like your right.....for this x86 assembly anyways.
Maybe Bubba can do some by-hand sloptamizations for us :)

gg
• 03-30-2004
Prelude
>I would argue that the statement is still well defined due to the left to right associativity
Section 5, paragraph 4 of the draft standard:
Code:

```Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [Example:         i = v[i++]; // the behavior is undefined         i = 7, i++, i++; // ‘i’ becomes 9         i = ++i + 1; // the behavior is undefined         i = i + 1; // the value of ’i’ is incremented —end example]```
Look up the definition of a sequence point and then tell me if ^= is one of them. :)
• 03-30-2004
Codeplug
Well, can't argue with that :p

>> i = v[i++]; // the behavior is undefined

Never looked a sequence points as encompassing both the rvalue's and lvalue's......interesting.
Although 99.9% of the time (if not 100%), compilers will implement the expected behavior......which of course, isn't an excuse for writting such code :)

gg
• 03-30-2004
Prelude
>Although 99.9% of the time (if not 100%), compilers will implement the expected behavior
This is true.

>which of course, isn't an excuse for writting such code
This is also true. :D But the issue of only being able to swap integral values and swapping a variable with itself (a very possible occurance) using an xor swap persist whether the swap is written correctly, or the compiler "does the right thing". There are too many silent restrictions with that construct for me to be entirely comfortable with it. Couple that with the obscure nature of xoring two values to implement a swap without a temporary and you have a nasty bug waiting to happen.