无类型指针的缺陷是无法对类型进行解释。(不能计算无类型的大小)

如,定义一个无类型指针:void *p

不能进行++p或者*p的操作,因为系统没有此地址指向对象大小的信息。

无内存重叠(从低地址开始复制)

头文件string.h中定义的memcpy()函数可以实现泛型的拷贝。

函数memcpy()

原型:void* memcpy(void *dest,void *src,unsigned int n)

作用:由src所指内存区域复制n个字节到dest所指内存区域。

说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。

现在我们编写自己的函数来实现泛型的拷贝。

void* my_memcpy(void *dst,const void *src,int size)
{if(di==NULL||si==NULL)return;void *ret=dst;char *d=(char *)dst;const char *s=(const char *)src;for(int i=0;i<size;i++){d[i]=s[i];}return ret;
}

参数size表示字节个数。

之所以将无类型指针强转为char型指针,只是因为char类型的大小是1字节,这样声明可以实现一个字节一个字节地复制。

主函数中调用这个函数:

int ar[10]={12,23,34,45,56,67,78,89,90,100};

int br[10];

float dr[10]={1.2,2.3,3.4,4.5,6.7,8.9,9.0,10.0};

float xr[10];

my_memcpy(br,ar,sizeof(ar)); //40

my_memcpy(xr,dr,sizeof(dr)); //80

进一步,还可以通过泛型拷贝来实现泛型的交换函数。

#include<stdio.h>
struct Student
{int id;char name[20];int age;
};
void Swap(void *a,void *b,int const n)
{if(a==NULL||b==NULL){return;}char temp;for(int i=0;i<n;++i){temp=((char *)a)[i];((char *)a)[i]=((char *)b)[i];((char *)b)[i]=temp;}
}
void main()
{char ca='a',cb='x';int ia=12,ib=23;double da=12.23,db=34.34;Student sa={2017,"yhping",18};Student sb={2018,"xcving",15};Swap(&ca,&cb,sizeof(ca));Swap(&da,&db,sizeof(da));Swap(&sa,&sb,sizeof(sa));
}

有内存重叠(从高地址开始复制)

当有内存重叠时,源地址src会被覆盖,因此有了memcpy()函数的改进版memmove()函数。

可以根据判断源地址和目的地址的大小,决定是从低地址开始拷贝还是从高地址开始拷贝。

void* my_memmove(void *dst,const void *src,int size)
{if(dst==NULL||src==NULL)return;void * ret = dst;if(dst <= src || (char *)dst >= ((char *)src + size))    //没有内存重叠,从低地址开始复制{    while(size--){   *(char *)dst = *(char *)src;dst = (char *)dst + 1;   src = (char *)src + 1; } }else    //有内存重叠,从高地址开始复制{    src = (char *)src + len - 1;  dst = (char *)dst + len - 1;  while(size--){   *(char *)dst = *(char *)src;   dst = (char *)dst - 1;   src = (char *)src - 1;  } } return ret;
}

相对全面的测试用例如下:

void Test()
{char p1[256] = "hello,world!";char p2[256] = {0};my_memmove(p2,p1,strlen(p1)+1);printf("%s\n",p2);my_memmove(NULL,p1,strlen(p1)+1);my_memmove(p2,NULL,strlen(p1)+1);my_memmove(p1+1,p1,strlen(p1)+1);printf("%s\n",p1);my_memmove(p1,p1+1,strlen(p1)+1);printf("%s\n",p1);
}

【C/C++】通过无类型指针实现泛型拷贝(内存拷贝)相关推荐

  1. C语言 void和void *(无类型指针)

    void 关键字 void的字面意思是"无类型",void *则为"无类型指针",void *可以指向任何类型的数据. void几乎只有"注释&quo ...

  2. 无类型指针、空指针和野指针

    1.无类型指针:void *p: 不指定它指向具体哪种数据类型.可以通过强制转化将void *转化为其他类型指针,也可以用(void *)将其他类型指针强制转化为void类型指针.指针之间赋值需要类型 ...

  3. C++中野指针和空指针和无类型指针

    C++中野指针和空指针和无类型指针https://blog.csdn.net/chenguolinblog/article/details/27054267 一. 野指针 所谓的野指针指的是一个指针变 ...

  4. c语言使用node类型指针,C语言利用 void 类型指针实现面向对象类概念与抽象

    不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...

  5. java什么是类型擦除_Java 泛型,你了解类型擦除吗?

    泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但 ...

  6. 【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 )

    文章目录 一.Dart 泛型类与泛型方法 二.Dart 泛型中的特定类型约束 三.Dart 自带泛型 四.完整代码示例 五. 相关资源 一.Dart 泛型类与泛型方法 泛型作用 : 为 类 , 接口 ...

  7. C++ void类型指针的使用

    一般情况下,指针的值只能赋给相同类型的指针.但是有一种特殊的 void类型指针,可以存储任何类型的对象地址,就是说任何类型的指针都可以赋值给void类型的指针变量.经过使用类型显示转换,通过void类 ...

  8. c语言char指针用法,整理C语言中各种类型指针的特性与用法

    2016 指针为什么要区分类型: 在同一种编译器环境下,一个指针变量所占用的内存空间是固定的.比如,在16位编译器环境 下,任何一个指针变量都只占用8个字节,并不会随所指向变量的类型而改变. 虽然所有 ...

  9. C++ 指向子类的指针转型为指向父类类型指针之后指向的对象地址不变

    C++ 指向子类的指针转型为指向父类类型指针之后指向的对象地址不变 例子: class A{int a;int b; };class B:public A{int c; };int main(){B* ...

最新文章

  1. 贪心 ---- 2020牛客多校第3场[Clam and Fish+贪心]
  2. python字符串的定义、切片、格式化、函数
  3. linux kernel makefile analysis
  4. leetcode算法题--0~n-1中缺失的数字
  5. python 慕课课程笔记(一)
  6. mysql可视化工具-navicat的下载和使用
  7. php中退出怎么写,php中退出登录怎么写
  8. Maximal Continuous Rest
  9. RESTful 架构风格概述
  10. mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决
  11. 译:重置/还原Windows IIs设置为默认设置
  12. paip.按键精灵调用其它程序及DLL以及EXE命令行的方法
  13. 计算机用于材料科学模拟,计算机在材料科学的应用
  14. 浏览器内核以及渲染过程
  15. Centos系统如何开启关闭防火墙
  16. 《三国演义》中的火烧赤壁居然也是假的!!
  17. 【写作中的复杂名词短语练习题】前置与后置修饰
  18. Linux系统常见命令缩写的由来
  19. MPP(大规模并行处理)简介
  20. Linux修改用户名

热门文章

  1. c++ ANSI、UNICODE、UTF8互转
  2. clion jiqiao
  3. [Java] 蓝桥杯ADV-166 算法提高 聪明的美食家
  4. [Java] 蓝桥杯BASIC-23 基础练习 芯片测试
  5. 【算法】动态规划笔记
  6. 通过java程序实现mysql 批量一个表的子段更新另一个表的字段
  7. Spring+MyBatis多数据源配置实现
  8. java 将 ResultSet 转化为 json格式
  9. 蚂蚁金服做区块链:我们绝不发空气币,要做就服务民生!
  10. Git学习系列之如何正确且高效地将本地项目上传到Github(图文详解)