strcpy及memcpy的内存重叠处理
strcpy和memcpy同是一个类型的函数,但实质上却是不同的,他们的原型分别为:
char *strcpy(char *dest, const char *src);
void *memcpy(void *dest, const void *src, size_t count);
当我们使用这两个函数时都会出现同样一个问题,内存重叠。那么我们就来分析一下内存重叠是如何产的。
现在假设有char *d = dest; char *s = src;要复制count = 5个字符,如下图所示:
1、第一种情况为 d <= s; 这种情况为d在s的后面,将s指向的东西往d指向的地方复制,d与s往后移动时内容互不干扰这是一种正常的状态。
2、第二种情况为d >= s + count; 这种情况是要复制的内容在两指针之间,此时指针移动时也不会对要复制的内容产生干扰,也不存在内重叠现象。
3、第三种情况时要复制的内容要比两指针的间距长,并且是由s往d中复制,如下图所示:
我们看到最后的结果变成了"hellh"而不是我们想要得到的"hello",于是,这就是产生内存重叠后的结果。解决内存重叠问题时我们可以将两个指针同时向后移动count-1个字节大小,让s指向要复制的最后一个元素的首地址,从后往前复制,如下图:
这样的处理后就能得到我们先要的结果了。下面时具体的代码实现。
void *memcpy(void *dest, constvoid *src,int count)
{
assert(dest != NULL);
assert(src != NULL);
char *d = dest;
char *s = src;
if(d <= s || d >= s + count)
{
while(count)
{
*d = *s;
d++;
s++;
count--;
}
}
else
{
d += count - 1;
s += count -1;
while(count)
{
*d = *s;
d++;
s++;
count--;
}
}
return dest;
}
(strcpy与之很相似,在这我就不写代码了)这就是内存重叠的处理方法。
接下来实现考虑内存重叠的strcpy的函数
注意事项:
1. 判断输入参数的合法性。
2. 要有返回的参数
3. 别忘了复制字符串末尾的'\0'
4. 如果内存有重叠,则倒着复制
当使用内存拷贝函数拷贝内容到新空间时我们会发现最后的结果会出现这样的东西:“”这是由于我们没有将'\0'给拷贝过去。指针会根据首地址寻找到原来首地址后边的东西,但当指针遇到'\0'时就停止寻址,所以要解决上述问题只需在最后加上'\0'即可。