C 语言实现泛型 swap 函数

由于 C 语言是强类型语言,所以通常我们在编写一些函数的时候就需要指定函数的类型。这就会导致同样的函数行为因为处理的类型不同,就可能需要为不同的类型编写不同的函数版本。

比如用于交换两个变量值的如 swap 函数:


void  swap(int  *v1, int  *v2)  {

    int *temp = v1;

    *v1 = *v2;

    *v2 = *temp;

}

上面的 swap 函数只能交换两个 int 类型的整数。

如果需要交换两个 double 类型的浮点数就需要再写一个 double 类型版本的 swap 函数:


void  swap(double  *v1, double  *v2)  {

    int *temp = v1;

    *v1 = *v2;

    *v2 = *temp;

}

所谓泛型swap函数就是一个 swap 函数就能够处理不同类型的交换工作。在 C++ 有模版来实现泛型,但是 C 语言中没有模板,所以我们可以使用 void 类型的指针来实现泛型swap函数,任何类型的指针都可以赋值给 void 类型的指针。

泛型swap函数实现:


    void  swap(void  *v1, void  *v2, size_t  size)  {

    void *temp = malloc(size);

    assert(temp != NULL);

    memcpy(temp, v1, size);

    memcpy(v1, v2, size);

    memcpy(v2, temp, size);

    free(temp);

}

先对函数中出现的 3 个函数分别加以说明:

  • malloc

函数原型为 void *malloc(size_t __size)。该函数用来向堆中动态申请一块内存。它会向堆中动态申请参数__size 个字节大小的内存空间,如果申请成功就返回申请到的空间首地址,申请失败就返回 NULL

  • memcpy

函数原型为 void *memcpy(void *dest, const void *src, size_t n)。该函数用来实现内存拷贝,它把参数 src 所指向的内存空间拷贝 n 个字节到参数 dest 所指向的内存空间中。

  • free

函数原型为 void free(void *ptr),该函数用来释放动态申请的内存。它把参数 ptr 所指向的动态申请的内存空间进行释放。

函数签名 void swap(void *v1, void *v2, size_t size) 中的前两个参数使用了 void 类型的指针,第三个参数 size 表示需要交换的类型在内存中所占字节数量。

第 2~3 行代码是向堆中申请 size 个字节大小的空间,然后将空间首地址赋值给 temp 指针,并断言内存是否申请成功。

第 4~6 行代码是通过内存拷贝的方式来实现交换步骤。

第 7 行代码是把在第 3 行代码中动态申请到的 size 个字节大小的内存空间进行释放,以免发生内存泄漏。

swap 函数进行调用,交换两个 int 类型变量的值:


int  main()  {

    int a = 123;

    int b = 321;

    printf("before swap: %d, %d\n", a, b);

    swap(&a, &b, sizeof(int));

    printf("after swap: %d, %d\n", a, b);

    return 0;

}

输出:


before swap: 123, 321

after swap: 321, 123

swap 函数进行调用,交换两个 double 类型变量的值:


int  main()  {

    double a = 123;

    double b = 321;

    printf("before swap: %f, %f\n", a, b);

    swap(&a, &b, sizeof(double));

    printf("after swap: %f, %f\n", a, b);

    return 0;

}

输出:


before swap: 123.000000, 321.000000

after swap: 321.000000, 123.000000

运行实现中的完整代码还需要引入头文件:


#include  <stdio.h>

#include  <stdlib.h>

#include  <string.h>

#include  <assert.h>

以上就是泛型 swap 函数的具体实现,主要是运用了 void 指针和内存拷贝。可以借鉴实现思路来研究关于 C 语言实现泛型的更多例子。

本作品采用《CC 协议》,转载必须注明作者和本文链接