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