1、memcpy和memmove的作用 & 区别
1.1、memcpy
memcpy
和memmove
都是C语言中的库函数,包含于头文件string.h
中。
void * memcpy ( void * destination, const void * source, size_t num );
memcpy的作用:
- 把source指针指向的位置处的num个字节的内存块拷贝到destination指针指向的位置处。
- 不允许源指针和目的指针指向的内存区域有重叠,会不安全。
1.2、memmove
void * memmove ( void * destination, const void * source, size_t num );
作用:
memmove
也可以把source指针
指向的位置处的num
个字节的内存块拷贝到destination指针
指向的位置处;- 和
memcpy
不一样的是,memmove
拷贝的时候会以一段缓冲区作为媒介,所以允许源指针和目的指针指向的内存区域有重叠。
2、内存重叠
下面举个例子说明一下内存重叠是什么意思:
- 当我们想把2 3 4 5拷贝到4 5 6 7处去的时候,这两块区域就发生了重叠;
- 如果使用memcpy的话,我们会发现2和3已经替代了4和5,我们没有办法再把4和5拷到6和7处去了,结果就变成了1 2 3 2 3 2 3 8,而这不是我们想要的结果;
- 但是使用memmove的话,我们还是可以得到1 2 3 2 3 4 5 8。
上面那个例子如果是从后往前拷的话就不会发生那样的问题!
再进一步总结:
- 只要目的地址在源地址之前就不会出现问题,可以从前往后拷;
- 若目的地址在源地址之后可能会有问题,需要从后往前拷。
3、代码实现
3.1、memcpy
//模拟实现memcpy
void* Memcpy(void* des, const void* src, size_t num)
{
if (des == NULL || src == NULL)
return NULL;
char* desStr = (char*)des;
const char* srcStr = (const char*)src;
while (num)
{
*desStr++ = *srcStr++;
--num;
}
return des;
}
3.2、memmove
//模拟实现memmove
void* Memmove(void* des, const void* src, size_t num)
{
if (des == NULL || src == NULL)
return NULL;
char* desStr = (char*)des;
const char* srcStr = (const char*)src;
if (des < src) //目的地址在源地址之前,从前往后拷
{
while (num--)
{
*desStr++ = *srcStr++;
}
}
else //目的地址在源地址之后,从后往前拷
{
while (num--)
{
*(desStr + num) = *(srcStr + num);
}
}
return des;
}
4、测试
void test()
{
int i = 0;
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int arr2[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
Memcpy(arr1, arr1+3, 4*sizeof(int));
Memmove(arr2 + 3, arr2 + 1, 4 * sizeof(int));
for (i = 0; i < 8; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
for (i = 0; i < 8; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
}
3、memset
void *memset(void *str, int c, size_t n)
作用:
- 复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
参数:
- str – 指向要填充的内存块。
- c – 要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
- n – 要被设置为该值的字符数。
测试:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[50];
strcpy(str,"This is string.h library function");
puts(str);
memset(str,'$',7);
puts(str);
return(0);
}
结果:
This is string.h library function
$$$$$$$ string.h library function
自己实现:
void *my_memset(void *dest, int set, unsigned len)
{
if (dest == NULL || len < 0)
{
return NULL;
}
char *pdest = (char *)dest;
while (len-->0)
{
*pdest++ = set;
}
return dest;
}