web-dev-qa-db-ja.com

Cに組み込みのスワップ関数はありますか?

3番目の変数を使用せずに動作するCの組み込みスワップ関数はありますか?

33
user1149207

いや.
C++にはありますが、_c = a;a = b; b = c;_のように機能します
C++組み込みスワップ関数:swap(first,second);
これを確認してください: http://www.cplusplus.com/reference/algorithm/swap/

これを使用して、3番目の変数を使用せずに2つの変数値を交換できます。

_a=a^b;
b=a^b;
a=b^a;
_

これも確認できます。

https://stackoverflow.com/questions/756750/swap-the-values-of-two-variables-without-using-third-variable

番目の変数なしでスワップする方法

27
Saif

なぜ3番目の変数を使用したくないのですか?これは、ほとんどのアーキテクチャで最速の方法です。

XORスワップアルゴリズム は3番目の変数なしで機能しますが、次の2つの点で問題があります。

  1. 変数は個別でなければなりません。つまり、swap(&a, &a)は機能しません。
  2. 一般的に遅いです。

3番目の変数を使用するとスタックがあふれる場合は、XORスワップを使用する方が望ましい場合がありますが、通常はそのような呼び出しを行うことができません。

質問に直接答えるために、標準Cにはスワップ関数はありませんが、書くのは簡単です。

24
Peter Alexander

標準Cにはそのような関数はありません。

(C++では、 std::swap() があります。)


この質問 のマクロが役に立つかもしれません。

8
Igor Oks

[〜#〜] c [〜#〜]ソロではなく、C++が必要な場合、少なくともGCC拡張機能を使用してマクロにすることができます。それは十分に一般的な、何かのような

_ #define SWAP(x,y) do {   \ 
   typeof(x) _x = x;      \
   typeof(y) _y = y;      \
   x = _y;                \
   y = _x;                \
 } while(0)
_

呼び出しなどのトリックに注意してくださいswap(t[i++],i);それらを回避するには、アドレス演算子_&_を使用します。そして、一時的なものを使用した方が良いでしょう(整数については、排他的論理和を使った有名で役に立たないトリックがあります)。

PS:読みやすくするために、おそらくコンパイラからの最適化を有効にするために、2つのローカル変数__x_および__y_を使用しています(ただし、1つのローカル変数のみを使用することもできます)。

Cには2つの変数を交換する標準関数はありません。

マクロは次のように記述できます。

#define SWAP(T, a, b) do { T tmp = a; a = b; b = tmp; } while (0)

マクロは次の方法で呼び出すことができます。

int a = 42;
int b = 2718;

SWAP(int, a, b);

SWAPマクロを記述するためのいくつかの解決策は避ける必要があります。

#define SWAP(a, b) do { a = b + a; b = a - b; a = a - b; } while (0)

オペランドが符号付きタイプの場合、オーバーフローが発生する可能性があり、符号付きオーバーフローは未定義の動作です。

また、このようなXORソリューションを最適化しようとするソリューションは避ける必要があります。

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

aは前のシーケンスポイントと次のシーケンスポイントの間で2回変更されるため、シーケンスポイントの規則に違反し、未定義の動作になります。

6
ouah

オブジェクト表現をCのunsigned char配列にコピーできるため、次のマクロを使用して任意の2つのオブジェクトを交換できます。

#define SWAP(X,Y) \
    do { \
        unsigned char _buf[sizeof(*(X))]; \
        memmove(_buf, (X), sizeof(_buf)); \
        memmove((X),  (Y), sizeof(_buf)); \
        memmove((Y), _buf, sizeof(_buf)); \
    } while (0)

GCCは場合によってはこれに最適なコードを生成します。あなたはあなたの仕事を続けることができないかもしれません...

2
u0b34a0f6ae

組み込みのスワップ機能はありませんが、これを試すことができます

a = a ^ b;

b = a ^ b;

a = b ^ a;

1
Saif

C++ライブラリ関数があります。 2つの整数変数の値を交換します。たとえば、swap(x、y);変数xとyの値を交換します。同様に、swap(mat [i] [j]、mat [j] [i]);行列matの2つの値、つまり行i列jの値と行j列iの値を交換します。

1

標準Cの任意の2つの値を交換するための型に依存しない関数を思いついたと思いますが、私は言語にかなり慣れていないので、何かを見落としているかもしれません。 XORスワップアルゴリズムを使用し、さらに最適化できると確信していますが、2番目の値が3番目の引数で指定された同じバイト数を指している限り機能します。

void swapn(void *a, void *b, size_t n) {
    if (a == b) {
        return;
    }

    size_t i;
    char *x = (char *)a,
        *y = (char *)b;

    for (i = 0; i < n; i++) {
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
        x++;
        y++;
    }
}

使用例:

// swap two integers
int x = 5,
    y = 30;

printf("%d\t%d\n", x, y);

swapn(&x, &y, sizeof(int));

printf("%d\t%d\n\n", x, y);

// swap two floats
float a = 9.23f,
    b = 6.83f;

printf("%.2f\t%.2f\n", a, b);

swapn(&a, &b, sizeof(float));

printf("%.2f\t%.2f\n\n", a, b);

// swap two doubles
double p = 4.7539,
    q = 0.9841;

printf("%.4f\t%.4f\n", p, q);

swapn(&p, &q, sizeof(double));

printf("%.4f\t%.4f\n\n", p, q);

// swap two chars
char m = 'M',
    n = 'n';

printf("%c\t%c\n", m, n);

swapn(&m, &n, sizeof(char));

printf("%c\t%c\n\n", m, n);

// swap two strings of equivalent length
char s[] = "Hello",
    t[] = "World";

printf("%s\t%s\n", s, t);

swapn(s, t, sizeof(s));

printf("%s\t%s\n\n", s, t);

出力は次のとおりです。

5   30
30  5

9.23    6.83
6.83    9.23

4.7539  0.9841
0.9841  4.7539

M   n
n   M

Hello   World
World   Hello
0
Patrick Roberts
#define swap(T, x, y) \
    {                 \
        T tmp = x;    \
        x = y;        \
        y = tmp;      \
    }

int main()
{
    int a = 10;
    int b = 20;
    printf("a=%d b=%d\n", a, b);
    swap(int, a, b);
    printf("a=%d b=%d\n", a, b);

    return 0;
}
0
Li Kui

がある std::swapスワップをサポートするかどうかは、一般的にプロセッサに依存するためです。 「比較とスワップ」と呼ばれる命令がありますが、レジスタに収まるタイプでのみ機能し、アトミックであることが保証されています。 gcc からの比較とスワップ(CAS)の組み込み実装があります。スレッドとミューテックスの実装の同期に使用され、おそらく目的の範囲外になるため、一時変数、または本当にCにこだわっている場合は、常に次のようなマクロを使用できます。

#define swap(a,b) a=a^b; \
                  b=a^b; \
                  a=b^a;
0
Alex