【C/C++】通过无类型指针实现泛型拷贝(内存拷贝)
无类型指针的缺陷是无法对类型进行解释。(不能计算无类型的大小)
如,定义一个无类型指针: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++】通过无类型指针实现泛型拷贝(内存拷贝)相关推荐
- C语言 void和void *(无类型指针)
void 关键字 void的字面意思是"无类型",void *则为"无类型指针",void *可以指向任何类型的数据. void几乎只有"注释&quo ...
- 无类型指针、空指针和野指针
1.无类型指针:void *p: 不指定它指向具体哪种数据类型.可以通过强制转化将void *转化为其他类型指针,也可以用(void *)将其他类型指针强制转化为void类型指针.指针之间赋值需要类型 ...
- C++中野指针和空指针和无类型指针
C++中野指针和空指针和无类型指针https://blog.csdn.net/chenguolinblog/article/details/27054267 一. 野指针 所谓的野指针指的是一个指针变 ...
- c语言使用node类型指针,C语言利用 void 类型指针实现面向对象类概念与抽象
不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...
- java什么是类型擦除_Java 泛型,你了解类型擦除吗?
泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但 ...
- 【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 )
文章目录 一.Dart 泛型类与泛型方法 二.Dart 泛型中的特定类型约束 三.Dart 自带泛型 四.完整代码示例 五. 相关资源 一.Dart 泛型类与泛型方法 泛型作用 : 为 类 , 接口 ...
- C++ void类型指针的使用
一般情况下,指针的值只能赋给相同类型的指针.但是有一种特殊的 void类型指针,可以存储任何类型的对象地址,就是说任何类型的指针都可以赋值给void类型的指针变量.经过使用类型显示转换,通过void类 ...
- c语言char指针用法,整理C语言中各种类型指针的特性与用法
2016 指针为什么要区分类型: 在同一种编译器环境下,一个指针变量所占用的内存空间是固定的.比如,在16位编译器环境 下,任何一个指针变量都只占用8个字节,并不会随所指向变量的类型而改变. 虽然所有 ...
- C++ 指向子类的指针转型为指向父类类型指针之后指向的对象地址不变
C++ 指向子类的指针转型为指向父类类型指针之后指向的对象地址不变 例子: class A{int a;int b; };class B:public A{int c; };int main(){B* ...
最新文章
- 贪心 ---- 2020牛客多校第3场[Clam and Fish+贪心]
- python字符串的定义、切片、格式化、函数
- linux kernel makefile analysis
- leetcode算法题--0~n-1中缺失的数字
- python 慕课课程笔记(一)
- mysql可视化工具-navicat的下载和使用
- php中退出怎么写,php中退出登录怎么写
- Maximal Continuous Rest
- RESTful 架构风格概述
- mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决
- 译:重置/还原Windows IIs设置为默认设置
- paip.按键精灵调用其它程序及DLL以及EXE命令行的方法
- 计算机用于材料科学模拟,计算机在材料科学的应用
- 浏览器内核以及渲染过程
- Centos系统如何开启关闭防火墙
- 《三国演义》中的火烧赤壁居然也是假的!!
- 【写作中的复杂名词短语练习题】前置与后置修饰
- Linux系统常见命令缩写的由来
- MPP(大规模并行处理)简介
- Linux修改用户名