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

Dr *_*Deo 17 c

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

题:

是否C标准库也有类似的功能,C++ std::swap()或我定义它自己.

ken*_*ytm 22

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

  1. C没有模板.
  2. 如果这样的功能确实存在,它看起来像void swap(void* a, void* b, size_t length),但不像std::swap,它不是类型安全的.
  3. 并且没有提示可以内联这样的函数,如果频繁交换(在C99中有inline关键字),这很重要.
  4. 我们也可以定义一个宏

    #define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
    
    Run Code Online (Sandbox Code Playgroud)

    但它会影响ttttttttt变量,你需要重复它的类型a.(在gcc中有typeof(a)解决这个问题,但你仍然不能SWAP(ttttttttt,anything_else);.)

  5. 并且编写交换也不是那么困难 - 它只是3行简单的代码!

  • 避免阴影`ttttttttt`,(如果该变量作为参数传入,则导致错误).你也可以调用变量`SWAP`. (4认同)

小智 13

C中没有等价物 - 事实上不可能,因为C没有模板功能.您必须为要交换的所有类型编写单独的函数.

  • @Dr Deo C没有很多C++所做的事情 - 这就是重点. (6认同)
  • 由于这通常是在宏中完成的,因此说“您必须为要交换的所有类型编写单独的函数”并不完全正确 (3认同)
  • @Ken实际上,在C++中,swap()用于各种"创造性"方式!其中大部分都不会适用于C代码. (2认同)

Pau*_*l R 9

如果你不介意使用C语言的gcc扩展,你可以用宏做类似的事情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;
}
Run Code Online (Sandbox Code Playgroud)

  • @Neil:是的,但是OP特别要求`C`实现.它远非一个完美的解决方案,但它是一个重要的C应用程序子集(IMNVHO)的合理解决方案. (2认同)
  • @CasperBeyer我不明白这对于“struct”类型如何工作 (2认同)

Kon*_*ski 6

这在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);
}
Run Code Online (Sandbox Code Playgroud)

现在解释它是如何工作的.首先,这SWAP()条线相对比较奇怪,但它实际上相对简单.&(a)a作为指针传递的参数.同样,&(b)参数b作为指针传递.

最有趣的代码是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);
      ^
Run Code Online (Sandbox Code Playgroud)

这个宏只评估一次(sizeof特殊,因为它不评估它的参数).这可以提供安全性,例如array[something()].我能想到的唯一限制是它不能对register变量起作用,因为它依赖于指针,但除此之外,它是通用的 - 你甚至可以将它用于变长数组.它甚至可以处理交换相同的变量 - 而不是你想要这样做.