本文讨论的是关于内存复制中内存重叠和不重叠的情况:
memmove
/**
* memmove - Copy one area of memory to another
* @dest: Where to copy to
* @src: Where to copy from
* @count: The size of the area.
*
* Unlike memcpy(), memmove() copes with overlapping areas.
*/
void *memmove(void *dest, const void *src, size_t count)
{
char *tmp;
const char *s;
if (dest <= src) {
tmp = dest;
s = src;
while (count--)
*tmp++ = *s++;
} else {
tmp = dest;
tmp += count;
s = src;
s += count;
while (count--)
*--tmp = *--s;
}
return dest;
}
函数说明:memmove()是从一个缓冲区移动到另一个缓冲区中。
返回值: 返回指向dest指针。
由于内存地址是线性的,在linux源码中memmove会对源地址和目标地址进行对别,以决定是从源内存块头部开始向尾部复制,还是从源内存快尾部向头部复制.
memcpy
/**
* memcpy - Copy one area of memory to another
* @dest: Where to copy to
* @src: Where to copy from
* @count: The size of the area.
*
* You should not use this function to access IO space, use memcpy_toio()
* or memcpy_fromio() instead.
*/
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
函数说明: memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束
返回值: 返回指向dest的指针
memcpy 并不考虑内存重叠的情况.
strcpy
char * strcpy (char * dst, const char * src)
{
char * cp = dst;
while( *cp++ = *src++ )
; /* Copy src over dst */
return( dst );
}
以上是通常代码
/* 代码风格应该是K&R风格 */
char *
strcpy (dest, src)
char *dest;
const char *src;
{
reg_char c;
/*
关于__unbounded和CHECK_BOUNDS_LOW,可以不作理会,可使其为空的宏定义。
引入这两个宏的原因是因为bounded pointer,其定义参见wiki:http://en.wikipedia.org/wiki/Bounded_pointer
*/
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
/*
计算目的地址dest与源地址s的偏移-1的值。之所以要减去1,是因为后面的代码。
*/
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
size_t n;
do
{
c = *s++;
/* 前面计算偏移的时候多减了一个1,就因为上一个语句s进行了自加运算 */
s[off] = c;
}
while (c != '\0');
/* 这部分代码也可以无视 */
n = s - src;
(void) CHECK_BOUNDS_HIGH (src + n);
(void) CHECK_BOUNDS_HIGH (dest + n);
return dest;
}
以上是个glibc代码.
可以看出均没有考虑内存重叠情况.