MMGameslogo  MMGames
TwitterSharebutton  FacebookSharebutton   
learn through sufferingC Language
learn through sufferingC Language

SWAP macro

SWAP macro
SWAP is a macro or function that exchanges the values of two variables.
This function itself is very simple, and paradoxically, because of that...
"Many people are wondering if it could be achieved with macros alone, and it's quite a hot topic."

Let's start by explaining the implementation from the most basic functions.
"Since I need to modify the values of two variables, I'm naturally using pointer arguments."
Then, all that remains is to swap the two variables on the function side, but the point to note is...

Source code
void swap(int* a, int* b)
{
    *a = *b;
    *b = *a;
    return;
}

That won't work.
Because the contents of *a* become identical to the contents of *b* at the moment *a* is assigned the value of *b*.
It's meaningless to substitute *a* for *b* afterward.

Therefore, you need to declare another local variable and store *a in it.
The following program is a typical implementation of a swap function.

Source code
#include <stdio.h>

void swap(int* a, int* b);

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

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

The results of this program are as follows:

Execution results
a = 10 : b = 100
a = 100 : b = 10

All that remains is to prepare them by type.
"In C, you won't be able to use features like inline functions, overloading, or templates."
You have to name and create each one individually, type by type.
"It's just not convenient, and even with C++, I'm concerned about the overhead of the calls."
There seem to be quite a few people who really want to achieve it with macros alone.

Initially, an implementation using addition and subtraction was considered.

Source code
#define SWAP(a, b) (a += b, b = a - b, a -= b)

The principle is simple."Add b first and save its value."
At first glance, an integer overflow might be a concern.
Even if an overflow occurs, the added value loops around, so it works without issues.

Another method utilizing the exclusive OR has also been devised.

Source code
#define SWAP(a, b) (a ^= b, b = a ^ b, a ^= b)

I'll omit the explanation of exclusive OR, but the underlying principle is fundamentally similar.
Generally, the exclusive OR is slightly faster than addition or subtraction, so we sometimes use it.
However, this limits its versatility as it cannot be used with real numbers.

These two macros generally work without issues.
Actually, there are cases where it doesn't work properly, and that's the biggest problem.
It occurs when the same variable is specified.
Actions speak louder than words, so I'm going to try it out myself.

Source code
#include <stdio.h>

#define SWAP(a, b) (a += b, b = a - b, a -= b)

int main(void)
{
    int a = 98;
    printf("a = %3d\n", a);
    SWAP(a, a);
    printf("a = %3d\n", a);
    return 0;
}

The results of this program are as follows:

Execution results
a = 98
a = 0

If you were to swap the values of the same variable a, the result should naturally remain unchanged.
This method results in a zero.
With this method, macros a and b always have the same value, so it's natural that the result is zero when you subtract them.
"By the method using exclusive OR, it also results in 0."

You might think that swapping the same variable would never happen,
In reality, in a sorting program, there was a time when i == j while swapping array[i] and array[j].
That's possible.Furthermore, most uses of SWAP are in sorting programs.

"It seems this problem is beyond resolution, so generally people don't delve any deeper."
The author is trying to resolve this, even by force, and is using the && operator to do so.
With the && operator, if the immediately preceding expression is false, the subsequent expression is not evaluated.
The following macro utilizes the properties of the && operator to perform a SWAP.

Source code
#define SWAP(a, b) ((a != b) && (a += b, b = a - b, a -= b))

This macro only performs the swap when the values of a and b are different.
"In other words, if a and b are the same variable, they will remain unchanged."
It might also be easier to do it as a function.

Alternatively, if you don't want to rely on the properties of operators, you can also use a ternary operator.

Source code
#define SWAP(a, b) ((a != b) ? (a += b, b = a - b, a -= b) : 0)

"The trailing zeros are dummy values inserted for grammatical consistency."
However, some compilers may issue a warning as an unnecessary expression.
With these macros, any variable of any type (including real numbers) can be swapped.
Only pointer variables that cannot perform addition or subtraction cannot be swapped.

You can create a SWAP macro if you don't use pointer variables.
"Exchanging pointer variables can only be implemented using the initial function provided, without exception."
And to make matters worse, sorting programs sometimes have to swap pointers as well.

Furthermore, rounding errors may occur when exchanging real numbers.
For example, if the value of variable 'a' is extremely large and the value of 'b' is extremely small,
Calculating a+b may result in a rounded value that is equal to a.
Therefore, it cannot be used when accuracy is required.

Ultimately, you'll inevitably need a temporary variable to reliably swap values.
Therefore, you need to declare variables within the macro.

Macros are essentially just replacements, so you can declare variables by specifying types.
Furthermore, you can avoid variable name collisions by enclosing them in curly braces {}.
Specifically, this will be as follows:

Source code
#define SWAP(type,a,b) { type temp = a; a = b; b = temp; }

While this macro requires specifying the type in the first argument, which slightly reduces its usability,
"Given the type, you can swap any variables."
Of course, it's also possible to swap values of real numbers and pointers.

The following program is an example of using this macro to swap variables.

Source code
#include <stdio.h>

#define SWAP(type,a,b) { type temp = a; a = b; b = temp; }

int main(void)
{
    int a = 10,b = 100;
    printf("a = %3d : b = %3d\n",a,b);
    SWAP(int,a,b)
    printf("a = %3d : b = %3d\n",a,b);
    return 0;
}

The results of this program are as follows:

Execution results
a = 10 : b = 100a = 100 : b = 10

Of course, it will also work fine if you specify the same variable.
This approach uses {} to enclose variable declarations.
It forms a complete sentence without the semicolon.
It's best not to include a trailing semicolon.

If you want to add a semicolon at the end.
最後に;をつけられないのは気持ち悪いという人は
#define swap(type,a,b) do{type _c;_c=a;a=b;b=_c;}while(0)
としてやればmacroだけでは文として完結しないので、
Finally, it will start working.



About This Site

Learning C language through suffering (Kushi C) is
This is the definitive introduction to the C language.
It systematically explains the basic functions of the C language.
The quality is equal to or higher than commercially available books.

Part 0: Program Overview
  1. What is a program?
Chapter 3: Displaying on the Screen
  1. String Display
  2. newline character
  3. Practice Problem 3
Chapter 4: Displaying and Calculating Numbers
  1. Display of numbers
  2. Basic calculations
  3. Numeric types
  4. Practice Problem 4
Chapter 6: Input from the Keyboard
  1. input function
  2. The fear of input
  3. Practice Problem 6
Chapter 9: Repeating a Fixed Number of Times
  1. Iterative sentence
  2. How Loops Work
  3. Practice Problem 9
Chapter 10: Repeating Without Knowing the Number of Times
  1. Unspecified loop
  2. Input validation
  3. Practice Problem 10
Chapter 13: Handling Multiple Variables at Once
  1. Handling multiple variables collectively.
  2. Arrays
  3. Practice Problem 13
Chapter 19: Dynamic Arrays
  1. Create arrays freely.
  2. Practice Problem 19