内存拷贝函数
memcpy
memcpy函数有三个参数,第一个是要拷贝的空间的起始地址,第二个是被拷贝的内容的起始地址,num是要拷贝的字节个数。意思就是从source的位置开始向后拷贝num个字节到dest所指向的空间,逐字节拷贝。memcpy不会关注字符串的结束标志等特殊字符,他只负责拷贝num个字节。同时memcpy不能用来拷贝两块有重叠的内存空间,因为从前向后逐字节拷贝会实时更新该空间的内容,可能达不到想要的效果。
C语言标准规定:memcpy用于拷贝两块独立空间中的内容,补用来处理重叠的内存之间的数据拷贝。 但是当我们使用vs中的memcpy函数时会发现它可以完成重叠内存的拷贝,这是因为vs编译器库里的memcpy的实现考虑到了这种情况,属于是超额完成任务,因为我们本身并没有要求他能实现这个功能。而我们要模拟的memcpy只用于两块独立内存的拷贝。
char* my_memcpy(void* dest, const void* source, size_t num)
{
assert(dest && source);
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)source;
((char*)dest)++;
((char*)source)++;
}
return ret;
}
memmove
memmove函数是用于有重叠空间的内存的拷贝。而memmove的实现与memcpy的实现是类似的,但是我们要考虑如何复制才不会覆盖为被拷贝的值。我们要分为两种情况来讨论,一是dest<source,这时候我们要从前往后赋值,当dest>source时,我们要从后往前复制。
void* my_memmove(void* dest, void* source, size_t num)
{
assert(dest && source);
char ret = dest;
if (dest < source)
{
for (int i=0;i<num;i++)
{
*((char*)dest+i) = *((char*)source+i);
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)source + num);
}
}
return ret;
}
内存比较函数
memcmp
memcmp函数是要比较两个指针开始往后的num个字节的内容的大小,这个函数是逐字节比较,所以比较时也要把指针临时强制转换成char* 类型来比较。
int my_memcmp(const void* s1, const void* s2, size_t num)
{
assert(s1 && s2);
while (num--)
{
if ((*(char*)s1) == (*(char*)s2))
{
((char*)s1)++;
((char*)s2)++;
}
else
{
return *(char*)s1 - *(char*)s2;
}
}
return 0;
}
内存设置函数
memset函数的功能是将从ptr开始的num个字节全部设置成value的值,这个函数之前已经讲过了,这里就直接模拟实现。
void* my_memset(void* ptr, int value, size_t num)
{
assert(ptr);
void* ret = ptr;
while (num--)
{
*((char*)ptr + num ) = value;
}
return ret;
}