是否有一个内置的方法来交换C中的两个变量

时间:2022-01-30 00:09:04

I know how to swap 2 variables in c++ , ie you use std::swap(a,b).

我知道如何在c++中交换两个变量(你使用std::swap) (a,b)

question:

问题:

Does the C standard library have a similar function to C++ std::swap() or do I have to define it myself.

C标准库是否与c++ std::swap()有相似的功能,还是必须自己定义。

10 个解决方案

#1


11  

There is no equivalent in C - in fact there can't be, as C doesn't have template functions. You will have to write separate functions for all the types you want to swap.

在C中没有等价的——事实上不可能有,因为C没有模板函数。您将不得不为您想要交换的所有类型编写单独的函数。

#2


20  

Yes you need to define it yourself.

是的,你需要自己定义它。

  1. C doesn't have templates.
  2. C没有模板。
  3. If such function does exist it would look like void swap(void* a, void* b, size_t length), but unlike std::swap, it's not type-safe.
  4. 如果该函数确实存在,它看起来就像void swap(void* a, void* b, size_t length),但不像std::swap,它不是类型安全的。
  5. And there's no hint such function could be inlined, which is important if swapping is frequent (in C99 there's inline keyword).
  6. 而且没有任何迹象表明这样的函数可以内联,这对于频繁交换非常重要(在C99中有inline关键字)。
  7. We could also define a macro like

    我们也可以定义一个像这样的宏

    #define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
    

    but it shadows the ttttttttt variable, and you need to repeat the type of a. (In gcc there's typeof(a) to solve this, but you still cannot SWAP(ttttttttt,anything_else);.)

    但是它在ttttttttttttttttt变量的阴影下,您需要重复a的类型(在gcc中有typeof(a)来解决这个问题,但是您仍然不能交换(ttttttttttttttt,anything_else);

  8. And writing a swap in place isn't that difficult either — it's just 3 simple lines of code!

    并且编写一个交换也不是那么困难——它只是3行简单的代码!

#3


9  

You can do something similar with a macro if you don't mind using a gcc extension to the C language, typeof:

如果您不介意将gcc扩展到C语言typeof,您可以使用一个类似的宏:

#include <stdio.h>

#define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while (0)

int main(void)
{
    int a = 4, b = 5;
    float x = 4.0f, y = 5.0f;
    char *p1 = "Hello";
    char *p2 = "World";

    SWAP(a, b); // swap two ints, a and b
    SWAP(x, y); // swap two floats, x and y
    SWAP(p1, p2); // swap two char * pointers, p1 and p2

    printf("a = %d, b = %d\n", a, b);
    printf("x = %g, y = %g\n", x, y);
    printf("p1 = %s, p2 = %s\n", p1, p2);

    return 0;
}

#4


7  

This works quickly in Clang and gcc (but not icc, which doesn't recognize this swap function - however, it will compile in any standard C99 compiler), provided that the optimizations actually recognize the swap (they do on high enough optimization levels).

这在Clang和gcc中工作得很快(但是icc不认识这个交换函数——但是,它将在任何标准的C99编译器中编译),前提是这些优化实际上能够识别交换(它们在足够高的优化级别上进行)。

#include <string.h>

#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
static inline void swap_internal(void *a, void *b, size_t size) {
    char tmp[size];
    memcpy(tmp, a, size);
    memmove(a, b, size);
    memcpy(b, tmp, size);
}

Now for explaining how it works. First, the SWAP() line is relatively strange, but it's actually relatively simple. &(a) is argument a passed as a pointer. Similarly, &(b) is argument b passed as an pointer.

现在来解释它是如何工作的。首先,SWAP()行比较奇怪,但它实际上相对简单。&(a)是作为指针传递的参数a。类似地,&(b)是作为指针传递的参数b。

The most interesting piece of code is sizeof *(1 ? &(a) : &(b)). This is actually a relatively clever piece of error reporting. If error reporting wouldn't be needed, it could be just sizeof(a). Ternary operator requires that its operations have compatible types. In this case, I check two different arguments for their type compatibility by converting them to pointer (otherwise, int and double would be compatible). As int * and double * aren't compatible, compilation would fail... provided it's standard C compiler. Sadly, many compilers assume void * type in this case, so it fails, but at least with a warning (that is enabled by default). To ensure correct size of the result, the value is dereferenced, and applied to sizeof, so there are no sideeffects.

最有趣的代码是sizeof *(1 ?&(a)和(b))。这实际上是一个相对聪明的错误报告。如果不需要错误报告,可以使用sizeof(a)。三元运算符要求其操作具有兼容的类型。在本例中,我通过将它们转换为指针(否则,int和double将是兼容的)来检查它们的类型兼容性的两个不同参数。由于int *和double *不兼容,编译将失败…提供它的标准C编译器。遗憾的是,许多编译器在这种情况下假定void *类型,所以它失败了,但是至少有一个警告(默认情况下是启用的)。为了确保结果的大小正确,将取消引用,并应用于sizeof,因此没有副作用。

~/c/swap $ gcc swap.c
swap.c: In function ‘main’:
swap.c:5:64: warning: pointer type mismatch in conditional expression [enabled by default]
 #define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                                ^
swap.c:16:5: note: in expansion of macro ‘SWAP’
     SWAP(cat, dog);
     ^
~/c/swap $ clang swap.c
swap.c:16:5: warning: pointer type mismatch ('int *' and 'double *') [-Wpointer-type-mismatch]
    SWAP(cat, dog);
    ^~~~~~~~~~~~~~
swap.c:5:57: note: expanded from macro 'SWAP'
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                        ^ ~~~~   ~~~~
1 warning generated.
~/c/swap $ icc swap.c
swap.c(16): warning #42: operand types are incompatible ("int *" and "double *")
      SWAP(cat, dog);
      ^

This macro evaluates everything exactly once (sizeof is special, as it doesn't evaluate its arguments). This provides safety against arguments like array[something()]. The only limitation I can think of is that it doesn't work on register variables because it depends on pointers, but other than that, it's generic - you can even use it for variable length arrays. It can even handle swapping identical variables - not that you would want to do that.

这个宏只计算一次所有内容(sizeof是特殊的,因为它不计算它的参数)。这为数组[something()]之类的参数提供了安全性。我能想到的唯一的限制是它不能对寄存器变量起作用,因为它依赖于指针,但是除此之外,它是通用的——你甚至可以对可变长度数组使用它。它甚至可以处理交换相同的变量——而不是你想做的那样。

#5


3  

In C this is often done using a macro,
there are very simplistic examples, eg:
#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}
... but I wouldn't recommend using them because they have some non-obvious flaws.

在C中,这通常是使用宏完成的,有一些非常简单的例子,例如:#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}…但我不建议使用它们,因为它们有一些不明显的缺陷。

This is a macro written to avoid accidental errors.

这是一个用于避免意外错误的宏。

#define SWAP(type, a_, b_) \
do { \
    struct { type *a; type *b; type t; } SWAP; \
    SWAP.a  = &(a_); \
    SWAP.b  = &(b_); \
    SWAP.t  = *SWAP.a; \
    *SWAP.a = *SWAP.b; \
    *SWAP.b =  SWAP.t; \
} while (0)
  • Each argument is instantiated only once,
    so SWAP(a[i++], b[j++]) doesn't give problem side effects.
  • 每个参数只实例化一次,所以交换(a[i++ +], b[j++])不会产生问题的副作用。
  • temp variable name is also SWAP, so as not to cause bugs if a different name happens to collide with the hard-coded name chosen.
  • temp变量名也是交换的,以便在不同的名称与选择的硬编码名称发生冲突时不会引起错误。
  • It doesn't call memcpy (which in fact ended up doing real function calls in my tests, even though a compiler may optimize them out).
  • 它不调用memcpy(实际上,它最终在我的测试中执行真正的函数调用,尽管编译器可能会对它们进行优化)。
  • Its type-checked
    (comparing as pointers makes the compiler warn if they don't match).
  • 它的类型检查(作为指针进行比较会使编译器在它们不匹配时发出警告)。

#6


0  

Another macro not already mentioned here: You don't need to give the type if you give the temporary variable instead. Additionally the comma operator is useful here to avoid the do-while(0) trick. But usually I don't care and simply write the three commands. On the other hand a temporary macro is useful if a and b are more complex.

这里没有提到的另一个宏:如果您提供临时变量,则不需要提供类型。此外,逗号操作符在这里是有用的,以避免do-while(0)技巧。但通常我不关心,只写三个命令。另一方面,如果a和b更复杂的话,临时宏是有用的。

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

void mix_the_array (....)
{
    int tmp;
    .....
    SWAP(pointer->array[counter+17], pointer->array[counter+20], tmp);
    .....
}

#undef SWAP

#7


0  

Check your compiler documentation. The compiler may have a swapb function for swapping bytes and my provide other similar functions.

检查你的编译器文档。编译器可能有交换字节的swapb函数和我提供的其他类似函数。

Worst case, waste a day and write some generic swap functions. It won't consume a significant amount of your project's schedule.

最坏的情况是,浪费一天时间编写一些通用的交换函数。它不会消耗大量的项目进度。

#8


0  

in essence, swap function is to swap two memory block. with two addresses and the size of block in bytes, we can swap pointers, integers, doubles, arrays, structs, ...

实质上,交换函数是交换两个内存块。有了两个地址和以字节为单位的块大小,我们就可以交换指针、整数、双精度、数组、结构、……

a pointer has three parts, e.g. we can break down short* p into three pieces

指针有三部分,例如,我们可以把短* p分成三部分

  1. address: void* p
  2. 地址:void * p
  3. size: reading two bytes at void*p, we get a short integer.
  4. 大小:在void*p中读取两个字节,得到一个短整数。
  5. usage: e.g. print a short integer with %hu
  6. 用法:例如,打印一个带有%hu的短整数

using the first two parts, we will be able to build a generic swap function:

使用前两部分,我们将能够构建一个通用的交换函数:

#include<stdint.h> 
#ifdef _WIN32
#define alloca _alloca
#else
#include <alloca.h>
#endif

void gswap(void * const a, void * const b, int const sz) {
    // for most case, 8 bytes will be sufficient.
    int64_t tmp; // equivalent to char tmp[8];
    void * p;
    bool needfree = false;
    if (sz > sizeof(int64_t)) {
        // if sz exceed 8 bytes, we allocate memory in stack with little cost.
        p = alloca(sz);
        if (p == NULL) {
            // if sz is too large to fit in stack, we fall back to use heap.
            p = malloc(sz);
            //assert(p != NULL, "not enough memory");
            needfree = true;
        }
    }
    else {
        p = &tmp;
    }

    memcpy(p, b, sz);
    memcpy(b, a, sz);
    memcpy(a, p, sz);

    if (needfree) {
        free(p);
    }

}

e.g.:

例如:

{// swap int 
    int a = 3;
    int b = 4;
    printf("%d,%d\n", a, b);//3,4
    gswap(&a, &b, sizeof(int));
    printf("%d,%d\n", a, b);//4,3
}
{// swap int64
    int64_t a = 3;
    int64_t b = 4;
    printf("%lld,%lld\n", a, b);//3,4
    gswap(&a, &b, sizeof(int64_t));
    printf("%lld,%lld\n", a, b);//4,3
}
{// swap arrays
    int64_t a[2] = { 3,4 };
    int64_t b[2] = { 5,6 };
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//3,4,5,6
    gswap(&a, &b, sizeof(a));
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//5,6,3,4
}
{// swap arrays
    double a[2] = { 3.,4. };
    double b[2] = { 5.,6. };
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//3.000000, 4.000000, 5.000000, 6.000000
    arrswap(&a, &b, sizeof(a));
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//5.000000, 6.000000, 3.000000, 4.000000
}

#9


-2  

You can do something similar with a macro without using temporary variable.

您可以在不使用临时变量的情况下对宏执行类似的操作。

#include <stdio.h>

#define SWAP(a, b) {a=a+b;b=a-b;a=a-b;} //swap macro
int main(void)
{
    int a = 4, b = 5;
    float x = 4.0f, y = 5.0f;
    char *p1 = "Hello";
    char *p2 = "World";

    a = 4, b = 5,x = 4.0f, y = 5.0f,*p1 = "Hello",*p2="world";
    SWAP(a, b); // swap two ints, a and b
    SWAP(x, y); // swap two floats, x and y
    SWAP1p1, p2); // swap two char * pointers, p1 and p2
    printf("a = %d, b = %d\n", a, b);
    printf("x = %g, y = %g\n", x, y);
    printf("p1 = %s, p2 = %s\n", p1, p2);

    return 0;
}

#10


-2  

In case of numeric values (at least):

数值(至少):

I know this is not an actual or complete answer but until now everyone has been making use of temporary variables so I thought Chris Taylors blog might be relevant to mention, it certainly does remove the need for typeof() etc.

我知道这不是一个实际的或完整的答案,但是到目前为止,每个人都在使用临时变量,所以我认为Chris Taylors博客可能是相关的,它确实消除了typeof()等的需要。

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

or

a = a + b;
b = a - b;
a = a - b;

In theory I suppose these techniques could be applied to strings and other types as well..

在理论上,我认为这些技术也可以应用到字符串和其他类型。

Still only three operations.

仍然只有三个操作。

#1


11  

There is no equivalent in C - in fact there can't be, as C doesn't have template functions. You will have to write separate functions for all the types you want to swap.

在C中没有等价的——事实上不可能有,因为C没有模板函数。您将不得不为您想要交换的所有类型编写单独的函数。

#2


20  

Yes you need to define it yourself.

是的,你需要自己定义它。

  1. C doesn't have templates.
  2. C没有模板。
  3. If such function does exist it would look like void swap(void* a, void* b, size_t length), but unlike std::swap, it's not type-safe.
  4. 如果该函数确实存在,它看起来就像void swap(void* a, void* b, size_t length),但不像std::swap,它不是类型安全的。
  5. And there's no hint such function could be inlined, which is important if swapping is frequent (in C99 there's inline keyword).
  6. 而且没有任何迹象表明这样的函数可以内联,这对于频繁交换非常重要(在C99中有inline关键字)。
  7. We could also define a macro like

    我们也可以定义一个像这样的宏

    #define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
    

    but it shadows the ttttttttt variable, and you need to repeat the type of a. (In gcc there's typeof(a) to solve this, but you still cannot SWAP(ttttttttt,anything_else);.)

    但是它在ttttttttttttttttt变量的阴影下,您需要重复a的类型(在gcc中有typeof(a)来解决这个问题,但是您仍然不能交换(ttttttttttttttt,anything_else);

  8. And writing a swap in place isn't that difficult either — it's just 3 simple lines of code!

    并且编写一个交换也不是那么困难——它只是3行简单的代码!

#3


9  

You can do something similar with a macro if you don't mind using a gcc extension to the C language, typeof:

如果您不介意将gcc扩展到C语言typeof,您可以使用一个类似的宏:

#include <stdio.h>

#define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while (0)

int main(void)
{
    int a = 4, b = 5;
    float x = 4.0f, y = 5.0f;
    char *p1 = "Hello";
    char *p2 = "World";

    SWAP(a, b); // swap two ints, a and b
    SWAP(x, y); // swap two floats, x and y
    SWAP(p1, p2); // swap two char * pointers, p1 and p2

    printf("a = %d, b = %d\n", a, b);
    printf("x = %g, y = %g\n", x, y);
    printf("p1 = %s, p2 = %s\n", p1, p2);

    return 0;
}

#4


7  

This works quickly in Clang and gcc (but not icc, which doesn't recognize this swap function - however, it will compile in any standard C99 compiler), provided that the optimizations actually recognize the swap (they do on high enough optimization levels).

这在Clang和gcc中工作得很快(但是icc不认识这个交换函数——但是,它将在任何标准的C99编译器中编译),前提是这些优化实际上能够识别交换(它们在足够高的优化级别上进行)。

#include <string.h>

#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
static inline void swap_internal(void *a, void *b, size_t size) {
    char tmp[size];
    memcpy(tmp, a, size);
    memmove(a, b, size);
    memcpy(b, tmp, size);
}

Now for explaining how it works. First, the SWAP() line is relatively strange, but it's actually relatively simple. &(a) is argument a passed as a pointer. Similarly, &(b) is argument b passed as an pointer.

现在来解释它是如何工作的。首先,SWAP()行比较奇怪,但它实际上相对简单。&(a)是作为指针传递的参数a。类似地,&(b)是作为指针传递的参数b。

The most interesting piece of code is sizeof *(1 ? &(a) : &(b)). This is actually a relatively clever piece of error reporting. If error reporting wouldn't be needed, it could be just sizeof(a). Ternary operator requires that its operations have compatible types. In this case, I check two different arguments for their type compatibility by converting them to pointer (otherwise, int and double would be compatible). As int * and double * aren't compatible, compilation would fail... provided it's standard C compiler. Sadly, many compilers assume void * type in this case, so it fails, but at least with a warning (that is enabled by default). To ensure correct size of the result, the value is dereferenced, and applied to sizeof, so there are no sideeffects.

最有趣的代码是sizeof *(1 ?&(a)和(b))。这实际上是一个相对聪明的错误报告。如果不需要错误报告,可以使用sizeof(a)。三元运算符要求其操作具有兼容的类型。在本例中,我通过将它们转换为指针(否则,int和double将是兼容的)来检查它们的类型兼容性的两个不同参数。由于int *和double *不兼容,编译将失败…提供它的标准C编译器。遗憾的是,许多编译器在这种情况下假定void *类型,所以它失败了,但是至少有一个警告(默认情况下是启用的)。为了确保结果的大小正确,将取消引用,并应用于sizeof,因此没有副作用。

~/c/swap $ gcc swap.c
swap.c: In function ‘main’:
swap.c:5:64: warning: pointer type mismatch in conditional expression [enabled by default]
 #define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                                ^
swap.c:16:5: note: in expansion of macro ‘SWAP’
     SWAP(cat, dog);
     ^
~/c/swap $ clang swap.c
swap.c:16:5: warning: pointer type mismatch ('int *' and 'double *') [-Wpointer-type-mismatch]
    SWAP(cat, dog);
    ^~~~~~~~~~~~~~
swap.c:5:57: note: expanded from macro 'SWAP'
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
                                                        ^ ~~~~   ~~~~
1 warning generated.
~/c/swap $ icc swap.c
swap.c(16): warning #42: operand types are incompatible ("int *" and "double *")
      SWAP(cat, dog);
      ^

This macro evaluates everything exactly once (sizeof is special, as it doesn't evaluate its arguments). This provides safety against arguments like array[something()]. The only limitation I can think of is that it doesn't work on register variables because it depends on pointers, but other than that, it's generic - you can even use it for variable length arrays. It can even handle swapping identical variables - not that you would want to do that.

这个宏只计算一次所有内容(sizeof是特殊的,因为它不计算它的参数)。这为数组[something()]之类的参数提供了安全性。我能想到的唯一的限制是它不能对寄存器变量起作用,因为它依赖于指针,但是除此之外,它是通用的——你甚至可以对可变长度数组使用它。它甚至可以处理交换相同的变量——而不是你想做的那样。

#5


3  

In C this is often done using a macro,
there are very simplistic examples, eg:
#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}
... but I wouldn't recommend using them because they have some non-obvious flaws.

在C中,这通常是使用宏完成的,有一些非常简单的例子,例如:#define SWAP(type,a,b) {type _tmp=a;a=b;b=_tmp;}…但我不建议使用它们,因为它们有一些不明显的缺陷。

This is a macro written to avoid accidental errors.

这是一个用于避免意外错误的宏。

#define SWAP(type, a_, b_) \
do { \
    struct { type *a; type *b; type t; } SWAP; \
    SWAP.a  = &(a_); \
    SWAP.b  = &(b_); \
    SWAP.t  = *SWAP.a; \
    *SWAP.a = *SWAP.b; \
    *SWAP.b =  SWAP.t; \
} while (0)
  • Each argument is instantiated only once,
    so SWAP(a[i++], b[j++]) doesn't give problem side effects.
  • 每个参数只实例化一次,所以交换(a[i++ +], b[j++])不会产生问题的副作用。
  • temp variable name is also SWAP, so as not to cause bugs if a different name happens to collide with the hard-coded name chosen.
  • temp变量名也是交换的,以便在不同的名称与选择的硬编码名称发生冲突时不会引起错误。
  • It doesn't call memcpy (which in fact ended up doing real function calls in my tests, even though a compiler may optimize them out).
  • 它不调用memcpy(实际上,它最终在我的测试中执行真正的函数调用,尽管编译器可能会对它们进行优化)。
  • Its type-checked
    (comparing as pointers makes the compiler warn if they don't match).
  • 它的类型检查(作为指针进行比较会使编译器在它们不匹配时发出警告)。

#6


0  

Another macro not already mentioned here: You don't need to give the type if you give the temporary variable instead. Additionally the comma operator is useful here to avoid the do-while(0) trick. But usually I don't care and simply write the three commands. On the other hand a temporary macro is useful if a and b are more complex.

这里没有提到的另一个宏:如果您提供临时变量,则不需要提供类型。此外,逗号操作符在这里是有用的,以避免do-while(0)技巧。但通常我不关心,只写三个命令。另一方面,如果a和b更复杂的话,临时宏是有用的。

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

void mix_the_array (....)
{
    int tmp;
    .....
    SWAP(pointer->array[counter+17], pointer->array[counter+20], tmp);
    .....
}

#undef SWAP

#7


0  

Check your compiler documentation. The compiler may have a swapb function for swapping bytes and my provide other similar functions.

检查你的编译器文档。编译器可能有交换字节的swapb函数和我提供的其他类似函数。

Worst case, waste a day and write some generic swap functions. It won't consume a significant amount of your project's schedule.

最坏的情况是,浪费一天时间编写一些通用的交换函数。它不会消耗大量的项目进度。

#8


0  

in essence, swap function is to swap two memory block. with two addresses and the size of block in bytes, we can swap pointers, integers, doubles, arrays, structs, ...

实质上,交换函数是交换两个内存块。有了两个地址和以字节为单位的块大小,我们就可以交换指针、整数、双精度、数组、结构、……

a pointer has three parts, e.g. we can break down short* p into three pieces

指针有三部分,例如,我们可以把短* p分成三部分

  1. address: void* p
  2. 地址:void * p
  3. size: reading two bytes at void*p, we get a short integer.
  4. 大小:在void*p中读取两个字节,得到一个短整数。
  5. usage: e.g. print a short integer with %hu
  6. 用法:例如,打印一个带有%hu的短整数

using the first two parts, we will be able to build a generic swap function:

使用前两部分,我们将能够构建一个通用的交换函数:

#include<stdint.h> 
#ifdef _WIN32
#define alloca _alloca
#else
#include <alloca.h>
#endif

void gswap(void * const a, void * const b, int const sz) {
    // for most case, 8 bytes will be sufficient.
    int64_t tmp; // equivalent to char tmp[8];
    void * p;
    bool needfree = false;
    if (sz > sizeof(int64_t)) {
        // if sz exceed 8 bytes, we allocate memory in stack with little cost.
        p = alloca(sz);
        if (p == NULL) {
            // if sz is too large to fit in stack, we fall back to use heap.
            p = malloc(sz);
            //assert(p != NULL, "not enough memory");
            needfree = true;
        }
    }
    else {
        p = &tmp;
    }

    memcpy(p, b, sz);
    memcpy(b, a, sz);
    memcpy(a, p, sz);

    if (needfree) {
        free(p);
    }

}

e.g.:

例如:

{// swap int 
    int a = 3;
    int b = 4;
    printf("%d,%d\n", a, b);//3,4
    gswap(&a, &b, sizeof(int));
    printf("%d,%d\n", a, b);//4,3
}
{// swap int64
    int64_t a = 3;
    int64_t b = 4;
    printf("%lld,%lld\n", a, b);//3,4
    gswap(&a, &b, sizeof(int64_t));
    printf("%lld,%lld\n", a, b);//4,3
}
{// swap arrays
    int64_t a[2] = { 3,4 };
    int64_t b[2] = { 5,6 };
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//3,4,5,6
    gswap(&a, &b, sizeof(a));
    printf("%lld,%lld,%lld,%lld\n", a[0], a[1], b[0], b[1]);//5,6,3,4
}
{// swap arrays
    double a[2] = { 3.,4. };
    double b[2] = { 5.,6. };
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//3.000000, 4.000000, 5.000000, 6.000000
    arrswap(&a, &b, sizeof(a));
    printf("%lf,%lf,%lf,%lf\n", a[0], a[1], b[0], b[1]);//5.000000, 6.000000, 3.000000, 4.000000
}

#9


-2  

You can do something similar with a macro without using temporary variable.

您可以在不使用临时变量的情况下对宏执行类似的操作。

#include <stdio.h>

#define SWAP(a, b) {a=a+b;b=a-b;a=a-b;} //swap macro
int main(void)
{
    int a = 4, b = 5;
    float x = 4.0f, y = 5.0f;
    char *p1 = "Hello";
    char *p2 = "World";

    a = 4, b = 5,x = 4.0f, y = 5.0f,*p1 = "Hello",*p2="world";
    SWAP(a, b); // swap two ints, a and b
    SWAP(x, y); // swap two floats, x and y
    SWAP1p1, p2); // swap two char * pointers, p1 and p2
    printf("a = %d, b = %d\n", a, b);
    printf("x = %g, y = %g\n", x, y);
    printf("p1 = %s, p2 = %s\n", p1, p2);

    return 0;
}

#10


-2  

In case of numeric values (at least):

数值(至少):

I know this is not an actual or complete answer but until now everyone has been making use of temporary variables so I thought Chris Taylors blog might be relevant to mention, it certainly does remove the need for typeof() etc.

我知道这不是一个实际的或完整的答案,但是到目前为止,每个人都在使用临时变量,所以我认为Chris Taylors博客可能是相关的,它确实消除了typeof()等的需要。

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

or

a = a + b;
b = a - b;
a = a - b;

In theory I suppose these techniques could be applied to strings and other types as well..

在理论上,我认为这些技术也可以应用到字符串和其他类型。

Still only three operations.

仍然只有三个操作。