一、memcpy
memcpy可以将src地址开始的整数个字节复制到目标dest地址区域。
void* mencpy(void* dest, const void* src, size_t len);
len是无符号整型,代表需要复制的字节数量,如果要复制4个int数据,那么len的值就是4*4=16个字节数。dest指向的内存空间与src指向的内存不能重叠。函数会返回一个地址,这个地址是目标dest的位置。
模拟实现memcpy函数:
(char*)dest++之所以会报错,是因为(char*)强制转换是临时的,操作完成后dest会变回viod
而(char*)dest++可以看作两行代码:
memcpy函数再复制的时候,严格按照字节数复制,复制字符时,遇见'\0'的时候并不会停止复制,做下测试
查看监视
可以看到memcpy函数在复制字符串时遇到'\0'不会停下来,并且在复制完后也不会给字符串添加'\0'。
dest指向的内存空间与src指向的内存如果重叠会出现什么情况:
要复制abcdef6个字符到a[2]处,理想结果是ababcdefij,结果发现ab循环了4次。这是因为memcpy函数是从低地址往高地址复制,如果dest地址和src重叠,并且dest在src地址之后,会出现覆盖数据的情况。
复制第一个字节:
复制第二个字节:
复制第三个字节:
从第三个字节就开始出错了。所以memcpy在dest和src重叠时会出错,如果想在重叠内存区域进行复制,需要使用memmove函数。
PS:VS2022的memcpy函数优化,即使内存空间重叠也能正常复制,效果与memmove一致。
二、memmove函数
void* memmove(void* dest, const void* src, size_t len);
menmove函数与memcpy类似,不过在源空间和目标空间重叠的情况下,能够正常复制数据。
模拟实现mommove函数:
dest和src的高低,会分为两种情况,第一种从低地址到高地址依次复制,第二种从高地址到低地址依次复制,这样就能避免memcpy的缺点了。
还是上个例子,如果从高到低复制:
第一次复制:
第二次复制:
第三次复制:
第四次复制:
第五次复制:
第六次复制:
如图可见,在这个例子里,如果从高地址往低地址复制,就不会出错了,所以memmove针对dest和src地址高低,对应了2种复制顺序,因此,可以用在内存空间重叠的情况下的复制。