C language learned by suffering
C language learned by suffering
SWAP macro
SWAP macro
SWAP is a macro or function that exchanges the values of two variables.
This function itself is very simple, but on the contrary, it is therefore
Many people wonder if it is possible to achieve this using only macros, and it has become quite a topic of discussion.
First, let's start with the most basic function implementation.
Since we need to change the value of two variables, we naturally use pointer type arguments.
All that's left to do is to swap the two variables on the function's side, but here's the catch.
This means that it is not possible to use the method of
Because once you assign *b to *a, the contents of *a are the same as the contents of *b, so
Substituting *a for *b after that is meaningless.
Therefore, it is necessary to declare another local variable and save *a there.
The following program is an example of the most standard implementation of the swap function.
The results of running this program are as follows
All that remains is to prepare this for each type.
Since features like inlining, overloading, and templates are not available in C
Each type must be named separately and created one by one.
That's hard to use, and even in C++, I'd be concerned about the overhead of calling
It seems that there are quite a few people who would like to somehow achieve this using only macros.
The first thought was to implement by addition and subtraction as follows.
The principle is simple. Add b first, and then store the value of b.
At first glance, overflow due to addition is a concern.
Even if it overflows, the added amount is looped over, so it works without any problem.
Another method using exclusive disjunction was also conceived.
I won't go into the details of exclusive disjunction, but in principle there is not much difference.
In general, exclusive or is slightly faster than addition or subtraction, so it is used in some cases.
However, it cannot be used for real values, making it less versatile.
In fact, there are cases where it does not work well, and that is the biggest problem.
It happens when the same variable is specified.
Since this is more proof than argument, we will actually try it out.
The results of running this program are as follows
If the values of the same variable, a, were exchanged, then of course the result should remain the same, but
This method results in 0.
In this method, a and b in the macro are always the same value, so it is natural that subtraction would result in 0.
Incidentally, the method using exclusive disjunction also yields 0.
You might think there's no such thing as interchanging the same variable.
In fact, in a sorting program, when exchanging array[i] and array[j], if i == j, then
This can happen. Moreover, most of the uses of SWAP are for sorting programs.
There's nothing we can do about this problem, so we generally don't seem to go any further into it.
The author wants to solve this problem by force, too, and uses the method with the && operator.
The && operator has the property that if the immediately preceding expression is false, the subsequent expression will not be executed.
The following macro is a SWAP macro that takes advantage of the && operator property.
This macro performs the exchange only when the values of a and b are different.
In other words, if a and b are the same variable, they are not exchanged and remain the same.
However, one might say that it is easier to make it a function than to do this.
Alternatively, if you do not want to depend on the nature of the operator, you can use the ternary operator.
The latter half of the 0 is a dummy value for grammatical consistency.
However, some compilers may warn you that it is a meaningless expression.
With these macros, variables of any type (even real numbers) can be exchanged, but
The only variable that cannot be exchanged is a pointer type variable that cannot be added or subtracted.
If you don't use pointer variables, you can make a SWAP macro, but
The only way to exchange pointer variables is inevitably to implement it by the function shown at the beginning.
And the trouble is that sometimes pointers are exchanged in sorting programs.
Furthermore, when exchanging real values, there is a potential for kerf loss.
For example, if the value of variable a is so huge and the value of b is so miniscule, then
Calculating a+b could result in rounding and the result being the same as a.
Therefore, it cannot be used when accuracy is required.
In the end, a temporary variable is inevitably needed to reliably exchange values.
To do so, the variable must be declared in the macro.
Since macros are merely replacements, variables can be declared by specifying their type.
You can also avoid variable name collisions by enclosing them in {} to block them.
Specifically, it looks like this
This macro is a little less convenient because it requires the type to be specified as the first argument, but it can be used with
Any variable can be exchanged as long as the type is specified.
Of course, real values and pointer values can also be exchanged.
The following program is an example of using this macro to exchange variables.
The results of running this program are as follows
Of course, the same variable works fine when specified.
Because this method encloses variable declarations in {}, the
The statement is complete without the ;;.
It is better not to put a ; at the end.
This function itself is very simple, but on the contrary, it is therefore
Many people wonder if it is possible to achieve this using only macros, and it has become quite a topic of discussion.
First, let's start with the most basic function implementation.
Since we need to change the value of two variables, we naturally use pointer type arguments.
All that's left to do is to swap the two variables on the function's side, but here's the catch.
source code
void swap(int* a, int* b)
{
*a = *b;
*b = *a;
return;
}
This means that it is not possible to use the method of
Because once you assign *b to *a, the contents of *a are the same as the contents of *b, so
Substituting *a for *b after that is meaningless.
Therefore, it is necessary to declare another local variable and save *a there.
The following program is an example of the most standard implementation of the 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 running this program are as follows
Execution Result
a = 10 : b = 100
a = 100 : b = 10
a = 100 : b = 10
All that remains is to prepare this for each type.
Since features like inlining, overloading, and templates are not available in C
Each type must be named separately and created one by one.
That's hard to use, and even in C++, I'd be concerned about the overhead of calling
It seems that there are quite a few people who would like to somehow achieve this using only macros.
The first thought was to implement by addition and subtraction as follows.
Source code
#define SWAP(a, b) (a += b, b = a - b, a -= b)
The principle is simple. Add b first, and then store the value of b.
At first glance, overflow due to addition is a concern.
Even if it overflows, the added amount is looped over, so it works without any problem.
Another method using exclusive disjunction was also conceived.
Source code
#define SWAP(a, b) (a ^= b, b = a ^ b, a ^= b)
I won't go into the details of exclusive disjunction, but in principle there is not much difference.
In general, exclusive or is slightly faster than addition or subtraction, so it is used in some cases.
However, it cannot be used for real values, making it less versatile.
These two macros work fine for the most part, but
In fact, there are cases where it does not work well, and that is the biggest problem.
It happens when the same variable is specified.
Since this is more proof than argument, we will actually try it out.
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 running this program are as follows
Execution Result
a = 98
a = 0
a = 0
If the values of the same variable, a, were exchanged, then of course the result should remain the same, but
This method results in 0.
In this method, a and b in the macro are always the same value, so it is natural that subtraction would result in 0.
Incidentally, the method using exclusive disjunction also yields 0.
You might think there's no such thing as interchanging the same variable.
In fact, in a sorting program, when exchanging array[i] and array[j], if i == j, then
This can happen. Moreover, most of the uses of SWAP are for sorting programs.
There's nothing we can do about this problem, so we generally don't seem to go any further into it.
The author wants to solve this problem by force, too, and uses the method with the && operator.
The && operator has the property that if the immediately preceding expression is false, the subsequent expression will not be executed.
The following macro is a SWAP macro that takes advantage of the && operator property.
Source code
#define SWAP(a, b) ((a ! = b) && (a += b, b = a - b, a -= b))
This macro performs the exchange only when the values of a and b are different.
In other words, if a and b are the same variable, they are not exchanged and remain the same.
However, one might say that it is easier to make it a function than to do this.
Alternatively, if you do not want to depend on the nature of the operator, you can use the ternary operator.
Source code
#define SWAP(a, b) ((a ! = b) ? (a += b, b = a - b, a -= b) : 0)
The latter half of the 0 is a dummy value for grammatical consistency.
However, some compilers may warn you that it is a meaningless expression.
With these macros, variables of any type (even real numbers) can be exchanged, but
The only variable that cannot be exchanged is a pointer type variable that cannot be added or subtracted.
If you don't use pointer variables, you can make a SWAP macro, but
The only way to exchange pointer variables is inevitably to implement it by the function shown at the beginning.
And the trouble is that sometimes pointers are exchanged in sorting programs.
Furthermore, when exchanging real values, there is a potential for kerf loss.
For example, if the value of variable a is so huge and the value of b is so miniscule, then
Calculating a+b could result in rounding and the result being the same as a.
Therefore, it cannot be used when accuracy is required.
In the end, a temporary variable is inevitably needed to reliably exchange values.
To do so, the variable must be declared in the macro.
Since macros are merely replacements, variables can be declared by specifying their type.
You can also avoid variable name collisions by enclosing them in {} to block them.
Specifically, it looks like this
Source code
#define SWAP(type,a,b) { type temp = a; a = b; b = temp; }
This macro is a little less convenient because it requires the type to be specified as the first argument, but it can be used with
Any variable can be exchanged as long as the type is specified.
Of course, real values and pointer values can also be exchanged.
The following program is an example of using this macro to exchange 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 running this program are as follows
Execution Result
a = 10 : b = 100a = 100 : b = 10
Of course, the same variable works fine when specified.
Because this method encloses variable declarations in {}, the
The statement is complete without the ;;.
It is better not to put a ; at the end.
If you want to put a ; at the end
If you feel weird about not being able to add a ; at the end, you can use
#define swap(type,a,b) do{type _c;_c=a;a=b;b=_c;}while(0)
The macro alone is not a complete statement, so you can use
It will work with a ; at the end.
#define swap(type,a,b) do{type _c;_c=a;a=b;b=_c;}while(0)
The macro alone is not a complete statement, so you can use
It will work with a ; at the end.
About this Site
The C language (bitter C), which is learned by suffering, is
This is the definitive C language introductory site.
It systematically explains the basic functions of the C language and
It is as complete as or better than any book on the market.