本质上,swap函数就是交换两个内存块。有了两个地址和块的大小(以字节为单位),我们可以交换指针、整数、双精度数、数组、结构......
指针由三个部分组成,例如我们可以将short* p 分解为三部分
- 地址:无效* p
- size:在
void*p处读取两个字节,我们得到一个短整数。
- 用法:例如用
%hu 打印一个短整数
使用前两部分,我们将能够构建一个通用的交换函数:
#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);
}
}
例如:
{// 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
}