C泛型___函数

对于c++等高级语言来说,语言本身提供了泛型模板,可以由编译器生成各种版本的完成相同功能的函数。
而对于c来说,我们怎么来完成这一切呢,我们可以充分利用指针来实现

示例1 交换两个元素
void swap(void* vp1, void* vp2, int size)
{
     char* cpTemp = new char[size];
     memcpy(cpTemp, vp1, size);
     memcpy(vp1,        vp2, size);
     memcpy(vp2, cpTemp,  size);
     delete []cpTemp;
}
调用: int i=10; int j= 20; swap(&i, &j, sizeof(int));
显然这样是不够安全的, 因为系统不会在乎传给vp1和vp2的指针是否是同一类型的指针,任何指针都可以很容易的转换成void型。那么就有可能出现数据被截断(传的是短类型的大小)或访问到未知内存的后果(传的是长类型的大小)
这些可以通过分别传入两个类型的大小实现,然后将大的类型截断和小类型交换。这只能保证没有内存错误,不能保证转换结果。因为你传入的是void指针,对于你的数据类型函数一无所知,也就不能实现在函数里的类型转换

示例2 找到数组array中的特定键值key  传回它第一次出现的地址
int lsearch(void* pkey, void* array, int n,  int elemsize, int(*pcmp)(void*, void*))
{
     for(int i=0; i<n; i++)
     {     
          char* pcurElem = (char*)array+i*elemsize;
          if(pcmp(pcurElem, pkey) == 0)
                    return i;
     }
     return -1;
}
//为什么要用自定义的pcmp比较函数而不用memcpy呢。原因很简单,对于数据类型char*来说,memcpy比较的是两个char*里面装的地址,而用户实际想比较的是它们指向的字符串。下面将提到这一点
cmp的示例
对于整型:
int cmp(void* vp1, void* vp2)
{
     int* ip1 = (int*)vp1;
     int* ip2 = (int*)vp2;
     return *ip1- *ip2;
}

对于字符串型:(即在一个字符串数组中寻找一个字符串)
int cmp(void* vp1, void* vp2)
{
     char* sp1 = *(char**)vp1;
     char* sp2= *(char**)vp2;
     return strcmp(sp1, sp2);
}
//考虑这里为什么用*(char**)vp1而不直接用char*vp1? 因为这里的vp2就是传入的pkey 是目标元素地址,而这里的目标元素是char* 因此需要对vp1,vp2转为本来的类型char**  再取得目标元素。 如果直接用char* vp1 并没有真正得到char*类型的目标元素。得到的是目标元素的地址,即将目标元素的地址强行看作了目标元素。在通俗一点,*(char**)实现了一次解引用,指针有一跳。而char* 只是一种原地强行解释,没有指针跳数
对于字符串型的测试:
void main()
{
     char* s[5] = {"my", "name", "is", "Daijun", "Wu"};
     char* aim = "Daijun"
     lsearch(&aim, s, 5, sizeof(char*), cmp);
}
熟悉这些操作可能并不能很快用于实际  但是可以对内存操作有更深一步的了解。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值