前言
对于字符串有一系列的字符串函数来操作字符串,比如strcpy、strcmp、strstr。但是这些函数都是只能用来操作字符串的,如果我们想要用来操作其他类型的数据的话就会有问题。这时就有一系列的内存操作函数来供我们使用,帮助我们更好地进行开发和工作。
内存操作函数的共性
我们先来找一找内存操作函数的共性,首先是看函数的定义部分,观察他们的返回类型,还有参数类型。
memcpy 函数的定义
memmove 函数的定义
memcmp 函数的定义
函数的共性
可以这些函数在定义的时候都是将需要操作的空间的使用void*
类型的形参来接受,为什么需要使用 void*
类型的指针来接受这个参数呢,这是因为函数的实现这并不知道会有什么类型的数据传进来,所以需要将函数的参数设为 void*
类型的指针(可以转变和接收为任意类型的指针)。而这些函数在传参的时候都会有一个size_t num
这是说明函数需要操作的空间大小,单位是字节。由于函数在实现的时候,操作的是空间大小的单位是字节。所以在模拟实现的时候就需要将指针转化为字符指针,因为字符指针刚好是一个字节一个字节操作的。
memcpy 函数【内存拷贝函数】
memcpy函数的定义
既然是函数,我们就需要将函数的返回类型还有参数的类型搞清楚,这样可以帮我们更好地掌握这个函数。
memcpy函数的定义
void * memcpy ( void * destination, const void * source, size_t num );
memcpy 函数,是将源空间后面的num个字节拷贝到目标空间后面的num个字节上。
模拟实现memcpy 函数
我们只需要将从source
开始到source + num - 1
的数据拷贝到从destination
开始,到destination + num - 1
的地址上去就可以了。
void* my_memcpy(void* dest, const void* src, size_t count) {
assert(dest && src); //判断指针不是空指针
void* ret = dest; //保留目标空间的起始位置
while (count--) { //控制循环保持在0 ~ count - 1
*(char*)dest = *(char*)src; //将源空间的内容一个字节一个字节地拷贝到目标空间
(char*)dest = (char*)dest + 1; //目标空间指向目标空间的下一个字节的地址
(char*)src = (char*)src + 1; //源空间指向源空间的下一个字节的地址
}
return ret; //返回目标空间的起始地址
}
使用前
使用后
memmove 函数
memcpy 函数在实现的时候如果目标空间和源空间存在空间重叠,那么就有可能将目标空间的值改变,然后拷贝到后面的目标空间。这样就达不到想要的效果。
使用前
使用后
所以需要一个memmove 来解决这一问题
memmove 函数的定义
memmove 函数的定义
void * memmove ( void * destination, const void * source, size_t num );
memmove 函数的模拟实现
解决这一问题,我们可以将源空间的内容拷贝到一个额外的空间里面,然后将这个额外的空间赋给目标空间,但是这种方法就需要额外的空间还有时间,效率有点低。所以我们需要一种更高效的方法,可以看到,如果目标空间的起始地址大于源空间的起始地址的时候,只需要从后面往前拷贝就行了,当目标空间的起始小于起始地址的时候,只需要按照从后往前拷贝的方式来拷贝就可以了。这时我们只需要进行一次判断然后执行对应的操作。就可以节省空间和时间了。
void* my_memmove(void* dest, const void* src, size_t count) {
assert(dest && src); //判断指针不为空
void* ret = dest; // 保存目标空间的地址
if (dest > src) { //判断是目标空间地址是否大于源空间地址
while (count--) {
*((char*)dest + count) = *((char*)src + count); //从后往前拷贝
}
}
else { //目标空间地址小于源空间地址
while (count--) {
*(char*)dest = *(char*)src; //从前往后拷贝
(char*)dest = (char*)dest + 1;
(char*)src = (char*)src + 1;
}
}
return ret; //实现链式访问
}
两个函数之间的差距就在重叠空间的拷贝,虽然现在在一些编译器下memcpy函数也可以实现重叠空间的拷贝,但是并不是全部编译器都可以实现。所以在编写代码的时候就需要严格得将两者分开,保证代码的可移植性。
memcmp 内存比较函数
memcmp 函数的使用可以对比strcmp函数,当空间1的数据小于空间2的数据,就返回下于0的数;两空间相等的话就返回0;当空间1的数据大于空间2的数据,就返回大于0的数。
memcmp 函数的定义
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
memcmp函数的模拟实现这里就不做讲解,可以参考strcmp的实现。
总结
本文仅仅简单得介绍了内存操作函数memcpy、memmove、memcmp,其中还有memcpy、memmove函数的模拟实现供大家参考,希望可以帮助到大家。