C 言語でのスワップ関数の実装

胡金庫 2023年10月12日
  1. 一時変数を使って C 言語でスワップ関数を実装する
  2. 算術演算を使用した C 言語でのスワップ関数の実装
  3. C 言語でビット単位の XOR 演算を使用してのスワップ関数の実装
  4. ビット単位の XOR 演算とマクロを使った C 言語でのスワップ関数の実装
C 言語でのスワップ関数の実装

この記事では、C 言語でスワップ関数を実装する方法について、いくつかの方法を解説します。

一時変数を使って C 言語でスワップ関数を実装する

スワップ関数は変数に対して行う代表的な操作です。C++ には std::swap 関数がありますが、C 標準ライブラリにはこの機能を提供する関数はありません。この記事では、積分値のスワップ関数を実装します。すなわち、ほとんどの関数は long int 型の引数を取りますが、常に異なる型に対して複数のプロトタイプを定義し、マクロ展開を用いて汎用的な機能を確保することができます。以下の例は、一時変数を使用したスワップ関数を示しています。最も簡単な実装ではありますが、以下に挙げた他の実装の中では比較的高速であることに注意してください(コンパイラの最適化を使用した場合)。

#include <stdio.h>
#include <stdlib.h>

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

int main(int argc, char *argv[]) {
  if (argc != 3) {
    printf("Usage: ./program first_number second_number/n");
    return 1;
  }

  long x = strtol(argv[1], NULL, 0);
  long y = strtol(argv[2], NULL, 0);

  printf("x:%ld, y:%ld\n", x, y);
  if (x != y) swap(&x, &y);
  printf("x:%ld, y:%ld\n\n", x, y);

  exit(EXIT_SUCCESS);
}

サンプルコマンド:

./program 123 432

出力:

x:123, y:432
x:432, y:123

算術演算を使用した C 言語でのスワップ関数の実装

あるいは、加算および減算演算のみを使ってスワップ関数を実装することもできます。関数内で渡されたポインタを操作することで、引数の値を直接変更することができます。main 関数では、オペランドが等しい場合に呼び出されないように、swap 関数が呼び出される前に if 条件を付けています。

#include <stdio.h>
#include <stdlib.h>

void swap(long *x, long *y) {
  *x = *x + *y;
  *y = *x - *y;
  *x = *x - *y;
}

int main(int argc, char *argv[]) {
  if (argc != 3) {
    printf("Usage: ./program first_number second_number/n");
    return 1;
  }

  long x = strtol(argv[1], NULL, 0);
  long y = strtol(argv[2], NULL, 0);

  printf("x:%ld, y:%ld\n", x, y);
  if (x != y) swap(&x, &y);
  printf("x:%ld, y:%ld\n\n", x, y);

  exit(EXIT_SUCCESS);
}

C 言語でビット単位の XOR 演算を使用してのスワップ関数の実装

スワップ関数の最もトリッキーでやや複雑な実装は、ビット単位の XOR 演算を使用するところです。このバージョンでは、先ほどの例のように第 3 の変数を必要としないことに注意してください。最初に、与えられた整数の XOR された結果をそれぞれの場所に格納します。次に、格納された値(y)をもう一方の整数で XOR し、その結果を後者の場所に格納します。最後に、両方の変数をもう一度 XOR 処理し、結果を最初に修正した変数-この場合は y に格納します。この実装では、最適化フラグを使用せずにコンパイルした場合、より多くのマシンコード命令が必要となり、より計算量の多いソリューションが得られます。

#include <stdio.h>
#include <stdlib.h>

void swap(long *x, long *y) {
  *y = *x ^ *y;
  *x = *x ^ *y;
  *y = *x ^ *y;
}

int main(int argc, char *argv[]) {
  if (argc != 3) {
    printf("Usage: ./program first_number second_number/n");
    return 1;
  }

  long x = strtol(argv[1], NULL, 0);
  long y = strtol(argv[2], NULL, 0);

  printf("x:%ld, y:%ld\n", x, y);
  if (x != y) swap(&x, &y);
  printf("x:%ld, y:%ld\n\n", x, y);

  exit(EXIT_SUCCESS);
}

ビット単位の XOR 演算とマクロを使った C 言語でのスワップ関数の実装

前の例で示したように、XOR スワップ関数は、関数のようなマクロとして実装することもできます。2つのオペランドが同じオブジェクトであるかどうかをチェックする必要があることに注意してください。このチェックは ?: 条件付きで実装されており、それを実行するだけで以前の実装と同様の XOR スワップアルゴリズムが実行されます。ただし、この関数のようなマクロは積分値しか処理できないことに注意してください。

#include <stdio.h>
#include <stdlib.h>

#define XORSWAP(a, b) \
  ((&(a) == &(b)) ? (a) : ((a) ^= (b), (b) ^= (a), (a) ^= (b)))

int main(int argc, char *argv[]) {
  if (argc != 3) {
    printf("Usage: ./program first_number second_number/n");
    return 1;
  }

  long x = strtol(argv[1], NULL, 0);
  long y = strtol(argv[2], NULL, 0);

  printf("x:%ld, y:%ld\n", x, y);
  XORSWAP(x, y);
  printf("x:%ld, y:%ld\n", x, y);

  exit(EXIT_SUCCESS);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook