1. 交换两个函数外部的元素值,直接看 demo

#include <stdio.h>

void Swap(int *a, int *b){
  int temp = *a;
  *a = *b;
  *b = temp;
}

int main(){

  int a = 1;
  int b = 2;

  printf("交换前的值,a:%d, b:%d", a, b);

  Swap(&a, &b);

  printf("\n交换后的值,a:%d, b:%d", a, b);

  return 0;
}

2. 上面的 Swap 函数是有问题的,原因在于只能交换 int 类型的两个变量的值,如果是其他变量则不行,所以考虑一个通用的交换版本,什么类型传进来都能交换

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

// size_t类型,目的是找一块不局限于某一类型的大小,详解 
// void*,可以接收任一类型的指针,使用的时候需要有具体的类型 https://zhuanlan.zhihu.com/p/98061960
void Swap(void *first, void *second, size_t size){

  void *temp = malloc(size);  // 开辟一块 size 大小的内存,其地址给 temp

  if(temp){  // 判断分配内存是否成功

    // 此处需要用到内存拷贝去复制值,不像之前的直接赋值
    memcpy(temp, first, size); // 从 first 指针指向的地址开始,复制 size 块内存的值到 temp指针指向的地址
    memcpy(first, second, size);
    memcpy(second, temp, size);

    free(temp);  // 不要忘记释放,自己申请的内存是存放在堆区的,不会自动释放
  }

}

int main(){

  double c = 3.0;
  double d = 4.0;
  printf("\n交换前的值,c:%f, d:%f", c, d);    // 交换前的值,c:3.000000, d:4.000000
  Swap(&c, &d, sizeof(double ));
  printf("\n交换后的值,c:%f, d:%f", c, d);    // 交换后的值,c:4.000000, d:3.000000

  return 0;
}

3. 对于这种不知道传来什么类型,可以利用宏,宏的参数可以是 int double 这种数据类型,所以可以定义一下临时变量进行使用

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

SWAP(c, d, double);
printf("\n交换后的值,c:%f, d:%f", c, d);    // 交换后的值,c:3.000000, d:4.000000

4. 更进一步,不传 int double 这种参数,因为传入的 a b 本身是包含了类型信息的,可以利用它们的信息来创建临时变量,改进上述宏。需要 mingw 编译器,因为它有一个 typeof 的关键字,可以获取参数的类型(msvc 编译器会报错:error C2146: 语法错误: 缺少“;”(在标识符“num”的前面)   error C2065: “num”: 未声明的标识符    error C2065: “num”: 未声明的标识符),这个改进的缺点的是代码不具备移植性,因为 typeof 不是 C 语言的特性

typeof(a) num = 0;    // 等同于 int num = 0;
printf("\nnum:%d", num);    // num:0

#define SWAP_S(a, b){typeof(a) temp; temp = a; a = b; b = temp;}

SWAP_S(c,d);
printf("\n交换后的值,c:%f, d:%f", c, d);    // 交换后的值,c:4.000000, d:3.000000

5. 还有一个问题,宏是替换还记不记得,宏里面定义了一个 temp 变量,如果在代码中也定义了 temp 变量,就会发生重复,所以在定义宏的时候,是有一个大括号的。但是大括号也带来一个问题,比如和 if 进行连用的时候:

if(a){
    b = 0;
};    // if 可以和; 进行配对,加了分号之后后面就不能添加 else了

#define SWAP_S(a, b){typeof(a) temp; temp = a; a = b; b = temp;}

if(a)
  SWAP_S(c,d);   // if(a) {typeof(a) temp; temp = a; a = b; b = temp;}; 因为宏里面有大括号,所以这里的情况就是 if 和 ; 进行配对,else会报错,解决方案是改写宏

else  // 报错:Expected expression
  printf("www");

// 改写宏,需要 do while帮忙,把 ; 处理一下
#define SWAP_T(a, b) do{typeof(a) temp; temp = a; a = b; b = temp;} while(0)
if(a)
  SWAP_T(c,d);   // if(a) do{typeof(a) temp; temp = a; a = b; b = temp;} while(0); 这里就可以连用 else 了
else
  printf("www");