1.1memcpy
函数声明
函数使用
函数模仿
既然会用了,不如在学会写,卷死他们。
首先先分析下函数声明:
void * memcpy ( void * destination, const void * source, size_t num );
无返回值。
然后函数里面是void*, 至于为什么要用void*:让我们换位思考下,假如我们现在是函数作者,是否知道用户要穿的是int* 还是char*?这是不可能知道的,因此我们需要个不挑食的“胖子”, void*。void*可以接收所有类型。 num就是要交换的字节数量。
函数具体实现方法
有图有真相。上代码。
void* my_memcpy(void* dest, const void* src, size_t count)
{
assert(src && dest);
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
上图解释代码:
函数不足
我们实现了函数,知道了内部表达。但是函数不足不知道有没有发现:如果source和destination有任何的重叠,复制的结果都是未定义的。
这句话是什么意思呢?
假如你让一个数组中前3个元素替换第2,3, 4个元素,这就有重叠了2,3。(在有些先进编译器是可以实现的,但在很多老版编译器中是实现不了的。)
那么,这样的缺陷需要怎么做?我们下面介绍新的函数:memmove完美解决了这个问题。
1.2 memmove
函数声明
函数使用
函数模仿
函数具体实现方法
请大家想一下,我们是否可以照搬用memmcpy的实现方法来实现?
我们来设想这样两个场景,一个是dest(接受地址的变量)> src(接受地址的变量)
另一个是dest < src。
上图:dest > src.
而当src > dest的时候,结果正好相反。就不能从后向前,不然也会出现覆盖现象,要从前向后。这样的话,我们就发现dest > / < src 是一个分水岭,而如果没有重叠的时候,从前到后和从后到前都是可以实现赋值操作的。
上代码:
void* my_memmove(void* dest, const void* src, size_t count)
{
assert(dest && src);
if (dest < src)
{
while (count++)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
}
、其实没啥好说的了。。。。。