変数の値を交換する | Programming Place Plus C言語編 逆引き

トップページC言語編逆引き

このページの概要

以下は目次です。

目的

2つの型が同じ変数があるとき、両者の値を入れ替えたいとします。 たとえば、以下のように2つの変数があるとき、

int x = 5;
int y = 10;

変数x の値が 10、変数y の値が 5 になるようにします。

なお、この処理は非常によく必要になるので、関数やマクロにすることを考えます。

方法①(一時変数を使う。関数版)

2つの変数のあいだで、同時に互いを代入できませんから、いったん、どちらかの変数の値を退避させる必要があります。

#include <stdio.h>

void swap(int* x, int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

int main(void)
{
    int x = 5;
    int y = 10;

    swap(&x, &y);
    printf("x == %d\n", x );
    printf("y == %d\n", y );
}

実行結果:

x == 10
y == 5

関数として実装する場合、引数はポインタにしなければなりません。 そうでないと、変数の値のコピーが渡されるだけなので、コピー同士の値が交換されるだけになり、無意味です。

型が固定されてしまうことが、C言語の関数を用いる場合の問題です。たとえば、double型の変数の値の交換のためには、中身は同じなのに、別の関数を用意しなければなりません。そこで、関数形式マクロを使った方法があります。

関数呼び出しのコストが気になる場合は、C99規格で追加された inline を使ってみましょう(第57章)。

方法②(一時変数を使う。マクロ版)

一時変数を使うという点では、方法①と変わりありませんが、 今度は関数形式マクロを使います。 この方法では、値を交換したい変数の型が何であるかを明示的に指定することで、型を問わずに汎用的に使用できます。

#include <stdio.h>

#define SWAP(type,x,y) do{type tmp = x; x = y; y = tmp;}while(0)

int main(void)
{
    int x = 5;
    int y = 10;

    SWAP(int, x, y);
    printf("x == %d\n", x );
    printf("y == %d\n", y );
}

実行結果:

x == 10
y == 5

SWAPマクロは何やら複雑ですが、交換をしている部分だけ抜き出すと、以下のようになります。

#define SWAP(type,x,y) type tmp = x; x = y; y = tmp;

マクロの中で、一時変数 tmp を定義していることがポイントです。 しかしこれだと、偶々 tmp という名前の変数があると、重複定義のエラーになってしまうので、 全体を { } で囲んでやる方が良いです。

do~while(0) で囲っているのは、

if(x != y)
    SWAP(int, x, y);
else
    puts("交換の必要なし!");

のように、{ } を伴わない if の中で使われるような状況を想定したものです。 マクロの置換結果の中で { } を使っているため、 こういう手を用いないと、if の { } と誤認され、構文エラーになってしまいます。


参考リンク


更新履歴

’2017/5/28 新規作成。



逆引きのトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る