一.memcpy函数(内存拷贝)
原型:void * memcpy ( void * destination, const void * source, size_t num );
解释:destination 目标空间(要拷贝的地点)source(起始空间)size_t num(要拷贝多少个字节) 同时为什么source这需要加const修饰,因为我们原空间内的数据是不变的,只是目标空间发生变化,让source受到保护。
1.memcpy库函数的使用:
举个例子:(图)
是指要从arr1中拷贝20个字节给arr2,也就是前5个整型(int 4B),这是我们使用库里的函数实现的,所以我们要引用头文件#include<string.h>。
2.模拟实现memcpy函数:(大家看一下注释,一步步非常详细)
#include<string.h>
#include <assert.h>
void* my_memcpy(void* dest,const void* src, size_t sz)//会改变目标空间,但不会改变src所以加个const修饰,让src受到保护,*src限制src改变
{
// void *指针是不能直接进行解引用加减操作的,要转化呀
char* ret = dest;//返回目标空间
assert(dest && src);//两个都不能为NULL
while (sz--)//字节数,拷贝完1个--
{
*(char*)dest = *(char*)src;//强转然后解引用 为什么是char 类型,因为不管想要拷贝几个字节都可以 如果整形正能拷贝偶数项那么奇数项就不行了,char拷贝几个都行
//所以一次拷贝1个字节拷贝sz次 sz--
dest = (char*)dest + 1;//为什么这右再次++,因为强制类型转换是临时的,所以再++之时还需要再转换
src = (char*)src + 1;//那能 (char*)dest++;不能在不同的编译器会出现错误,因为++的优先级更高,所以先++再强制转换,在强制转换前就已经改变了数
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5 };
my_memcpy(arr1, arr2, 20);//要拷贝20个字节 把arr2中的前五个整型,拷贝到arr1中,
return 0;
}
二.memmove函数(内存拷贝)
原型:void * memmove ( void * destination, const void * source, size_t num );
那其实与memcpy都是内存拷贝,那有什么区别呢?
那之前我们是在两个数组中进行,而在一个数组进行内存重叠拷贝可以吗?让我们试一下。
1.memmove库函数的使用
解释:大致意思是要把3 4 5 6 7 拷贝到1 2 3 4 5 上进行内存的重叠拷贝
arr+2指向3 要拷贝20个字节 拷贝到目标空间arr 指向1的位置
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr, arr + 2, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
2.模拟实现memmove函数
(1)首先我们先要分析一下从前往后比还是从后往前比较呢
地址是由低到高的,当地址dest<src时3拷贝到1,4-2 ,5-3,6-4,7-5,这样可以的它不至于把数据给挡了。当src<dest时由后到前。当在7之后,两者都可以。
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t sz)
{
char* ret = dest;
assert(dest && src);
前-后
if (dest < src)//地址的大小 由低到高 dest再src的左边 前到后
{
int i = 0;
for (i = 0; i < sz; i++)
{
*(char*)dest = *(char*)src;
dest=(char*)dest + 1;
src = (char*)src + 1;
}
}
else
{ //后到前
while (sz--)//--之后sz为19
{
*((char*)dest+sz) = *((char*)src+sz);
}
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr, arr + 2, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
问题思考?
在上面我们知道了memcpy和memmove都是内存拷贝,有什么样的区别呢?
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
/*my_memcpy(arr1+2, arr1, 20);*///会实现吗 最后发现时1 2 1 2 1 2根本不是想要的,因为memcpy
//是实现不重叠的内存实现拷贝
//而memmove是实现重叠的内存拷贝
/*my_memmove(arr1 + 2, arr1, 20);*///是可以的 12123458910
// 那对于刚才我们自己写的函数不行,那真的是我们写的不行
// 吗?并不是,memcpy是拷贝未重叠部分,而使用库函数是可以的
memcpy(arr1 + 2, arr1, 20);//是可以的,当使用库函数时memcpy可以拷贝重叠部分
return 0;
}
三.memset(设置内存函数,以字节为单位设置内存)
原型:void* memset(void* ptr, int value, size_t num);
是指:ptr所指向的前num个字节的值设置specific(具体 特殊的)为value
#include<string.h>
int main()
{
/*char arr[] = "hello bit";
memset(arr + 6, 'w', 3);*/
int arr[10] = { 0 };
memset(arr , 1,10);//这里调试 内存 成为 了 01 01 01 01因为它是以字节为单位并不是整型,并不是10个1
printf("%s\n", arr);
return 0;
}
四.memcmp函数(比较两个内存块,以字节来比较内存比较,无论什么类型都是内存中的数来比)
原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7 };//内存中这样存的 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00
//int arr2[] = { 1,2,3 }; //01 00 00 00 02 00 00 00 03 00 00 00相比较相等0
int arr2[] = { 1,2,3 ,0x11223344 };//小端存储
// 内存中 01 00 00 00 02 00 00 00 03 00 00 00 44 33 22 11
int ret=memcmp(arr1, arr2, 13);//第13个字节也就是从03 和44比较 <所以为负数,不要眼见比较,要在内存内
printf("%d\n", ret);
return 0;
}