Bootstrap

C语言内存函数

这里主要介绍两个内存函数:memcpy和memmove

这两个函数都是库函数。

memcpy

作用:这个函数和strcpy的作用是一样的,区别在于strcpy只能对字符串进行复制,而memcpy是对任意类型都能起作用。把源数据复制到目标数据内存,使原来的目标数据被源数据所替代。但它不能操作源内存和目标内存有重叠部分的两块内存。

void *memcpy (void * p1, const void * p2, size_t num)

这个函数有三个参数,第一个参数是目标数据,第二个参数是源数据,第三个参数是要复制的内存大小,单位是字节。返回类型是void *。

模拟实现memcpy

void * My_memcpy(void * dest, const void * sour, size_t num)
{
   assert(dest && sour);
   void * flag = (char*)dest;
   while(num--)
   {
     *(char*)dest = *(char*)sour;
     dest = (char*)dest+1;
     sour = (char*)sour+1;
   }
   return flag;
}

int main(  )
{ 
  int dest[] = {1,1,1,1,1};
  int sour[] = {2,2,2,2,2};
  My_memcpy(dest,sour,5*sizeof(int));

  for(int i = 0; i < 5; i++)
  {
     printf("%d ",dest[i]);
  }

  return 0;
}

需要注意的是,赋值以后,指针再移动。以及,返回类型是void *,一个字节一个字节地把源内存的数据赋值到目标内存。

memmove

作用:和memcpy作用相同,但多出一个功能。在源内存和目标内存有重叠的时候,可以用memmove来复制数据。

void * memmove (void *p1, const void *p2, size_t num)

三个参数和返回类型与memcpy相同。

模拟实现memmove

void * My_memmove (void *dest, const void *sour, size_t num)
{ 
  assert(dest && sour);
  void *flag = (char*)dest;

  if(dest < sour)
  {
    //从前向后
    while(num--)
    { 
      *(char*)dest = *(char*)sour;
      dest = (char*)dest + 1;
      sour = (char*)sour + 1;
    } 
  }
  else
  {
    //从后向前
    while(num--)
    {
     *((char*)dest + num) = *((char*)sour + num);
    }
  }
  
  return flag;
}

int main( )
{ 
   int arr[] = {1,2,3,4,5};
   My_memmove(arr+2,arr,3*sizeof(int));

   for(int i = 0; i < 5; i++)
   {
       printf("%d ", arr[i]);
   }

   return 0;
}

考虑到有重叠的内存,所以不能像memcpy那样只管从第一个赋值到最后一个,还要考虑重叠部分的内存。这时从后向前赋值就能避免赋值不到位的部分。因此分为两种情况讨论。如果目标地址小于源内存地址,那么两个指针向前移动,目标内存和源内存一一对应赋值,源内存不会提前被梗改和占用(因为目标内存永远在它后面,追不上它)。如果目标地址大于或者等于源内存地址,就可能出现本来是源内存需要被赋值给目标内存的,但却提前作为目标内存被赋值了,目标内存(就不能再转变为源内存)赋值给其他目标内存了。。值已经变化了。那么从后向前赋值就能解决这个问题。

;