linux源码中关于内存移动或复制的函数详细解说: memmove, memcpy, strcpy

本文详细探讨了Linux环境下,用于内存移动和复制的三个关键函数:memmove、memcpy和strcpy。memmove能处理内存重叠情况,确保安全移动;memcpy则适用于不重叠内存的快速复制;而strcpy在复制字符串时未考虑内存重叠,可能导致问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文讨论的是关于内存复制中内存重叠和不重叠的情况:


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代码.

可以看出均没有考虑内存重叠情况.






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值