C中是否有内置交换功能?

时间:2012-01-14 12:16:15

标签: c swap

C中是否有内置交换功能,不使用第三个变量?

11 个答案:

答案 0 :(得分:27)

没有。
C ++有,但它的工作方式与c = a;a = b; b = c;一样 C ++内置交换函数:swap(first,second);
检查一下:http://www.cplusplus.com/reference/algorithm/swap/

您可以使用它来交换两个变量值而不使用第三个变量:

a=a^b;
b=a^b;
a=b^a;

您也可以查看:

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

How to swap without a third variable?

答案 1 :(得分:24)

为什么你不想使用第三个变量?这是绝大多数架构上最快的方式。

XOR swap algorithm没有第三个变量,但在两个方面存在问题:

  1. 变量必须是不同的,即swap(&a, &a)不起作用。
  2. 一般来说速度较慢。
  3. 有时最好使用XOR交换,如果使用第三个变量会导致堆栈溢出,但通常你不能进行该调用。

    直接回答你的问题,标准C中没有交换功能,尽管写起来很简单。

答案 2 :(得分:8)

标准C中没有这样的功能。

(在C ++中你有std::swap()。)


来自this question的宏可能对您有用。

答案 3 :(得分:8)

假设你想要 C solotion,而不是 C ++ ,你可以把它变成一个宏,至少使用GCC扩展来使它足够通用,比如< / p>

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

谨防调用swap(t[i++],i)之类的技巧;要避免它们,请使用地址运算符&。而且你最好使用一个临时的(对于整数,有一个着名的,无用的技巧与独占或者)。

PS:我正在使用两个局部变量_x_y(但我本来只能使用一个局部变量)以获得更好的可读性,也许还可以实现更多优化编译器。

答案 4 :(得分:6)

C中没有标准函数来交换两个变量。

宏可以这样写:

#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在前一个和下一个序列点之间被修改两次,因此它违反了序列点规则并且是未定义的行为。

答案 5 :(得分:2)

由于您可以将任何对象表示复制到C中的unsigned char数组中,因此以下宏允许您交换任意两个对象:

#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甚至会在某些情况下为此生成最佳代码。你可能不会继续工作......

答案 6 :(得分:1)

没有内置交换功能,但你可以试试这个

a = a ^ b;

b = a ^ b;

a = b ^ a;

答案 7 :(得分:1)

有一个C ++库函数。它交换两个整数变量的值。例如,swap(x,y);将交换变量x和y的值。同样,交换(mat [i] [j],mat [j] [i]);将在矩阵mat中交换两个值,即第i行第j列中的值和第j行第i列中的值。

答案 8 :(得分:0)

std::swap因为一般来说它取决于您的处理器,是否支持交换。有一个称为“比较和交换”的指令,但它只适用于适合寄存器并保证是原子的类型。有一个来自gcc的比较和交换(CAS)的内置实现,它用于线程和互斥实现的同步,可能超出了你的目的范围,所以最好坚持使用临时变量或如果你真的坚持C,你总是可以使用这样的宏:

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

答案 9 :(得分:0)

我相信我已经想出了一个类型无关的函数来交换标准C中的任何两个值,但是因为我对这种语言很新,我可能忽略了一些东西。它使用XOR交换算法,我确信它可以进行更多优化,但只要两个值指向由第三个参数指定的相同字节数,它就可以工作:

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

答案 10 :(得分:0)

#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;
}