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");