往期回顾:
【C语言】带你手撕字符函数和字符串函数(1)(内含部分库函数模拟实现)
【C语言】带你手撕字符函数和字符串函数(2)(内含字符串查找函数、字符分类函数等)
本篇文章是字符函数系列的最终章,篇幅不会很长,我们将一起来学习三个常用的内存操作函数:memcpy、memmove和memcmp函数。
话不多说直接上货
1 memcpy
1.1 memcpy的定义
memcpy是用来将源空间中指定大小字节的数据复制到目标空间的函数。定义如下:
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。(注意:这里的num是字节的参数,而不是元素个数的参数)
这个函数遇到'\0'的时候不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的
为什么在这里,参数destination和source的返回类型是void*类型呢?
这样做可以使这个函数变成通用函数。设计者在设计函数时,并不知道在将来使用这个函数的人会用其复制哪种数据类型,因此在这里统一设置成void*类型。
void*类型也被称为通用类型指针,它的特点是可以接收任意类型数据的地址
1.2 memcpy的模拟实现
既然memcpy是逐个字节拷贝数据,且接受的参数是void*类型,那我们就可以将参数指针通过强制类型转换成char*类型。由于char类型占用大小是一个字节,那么char*指针每次加1就能跳过一个字节。
void *my_memcpy(void* dest, const void* src, size_t size)
{
void* ret = dest;
while (size--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
2 memmove
2.1 memmove的定义
memmove其实跟memcpy很像,区别在于memmove处理的源内存块和目标内存块是可以重叠的,而memcpy则不行。
因此,如果遇到源内存块和目标内存块重叠的情况,就用memmove函数处理
2.2 memmove函数的模拟实现
memmove函数模拟的实现较为复杂
void* my_memmove(void* dest, const void* src, size_t size)
{
void* ret = dest;
if (dest <= src || (char*)dest >= (char*)src + size)
{
while (size--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
dest = (char*)dest + size - 1;
src = (char*)src + size - 1;
while (size--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest - 1;
src = (char*)src - 1;
}
}
return ret;
}
3 memcmp
3.1 memcmp的定义
函数memcmp比较从ptr1和ptr2两个指针开始的num个字节
返回值如下:
其实memcmp的返回跟strcmp非常相似,只是memcmp不仅仅可以用来比较字符串大小,使用更加灵活
3.2 memcmp的模拟实现
此处可以类比strcmp的模拟实现,稍作修改即可写出memcmp
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
assert(ptr1 && ptr2);
while (num--)
{
if (*(char*)ptr1 == *(char*)ptr2)
{
((char*)ptr1)++;
((char*)ptr2)++;
}
else
return (*(char*)ptr1 - *(char*)ptr2);
}
return 0;
}
至此,字符函数和字符串函数系列结束