内存操作函数memcpy和memmove详解
内存操作函数memcpy和memmove详解
在C/C++中,根据定义,字符串由一个'\0'字节结尾,所以字符串内部不能包含'\0'字符。但是,非字符串数据内部包含'\0'的情况并不少见。你无法使用字符串函数(strcpy,strcat,strcmp等等字符串处理函数)来处理这种类型的数据,因为它们遇到第一个'\0'之后就停止工作。
因此C/C++中提供了另外一组mem***函数来处理内存操作,它们可以处理包括'\0'在内的任意字节,这些函数都接受一个长度参数。memcpy从源参数向目标参数复制由长度参数指定的字节数。memmove函数执行相同的功能,但它功能更加强大,能够正确处理源参数和目标参数出现内存重叠的情况。但通常由于memmove无法使用某些机器提供的特殊字节-字符串处理指令,所以它可能比memcpy慢一些。
源参数和目标参数在内存中分布情况分为重叠和不重叠,而重叠又分为源参数在目标参数的前面和源参数在目标参数的后面。memcopy只能处理不重叠和源参数在目标参数的后面的情况,而memmove能处理所有的情况。具体可以参考如下代码:
void *memcpy (void *dst, void *src, size_t length) { if (NULL == dst || NULL == src) return NULL; char *temp_dst = (char*)dst; char *temp_src = (char*)src; for (size_t len = 0; len < length; ++len) //从前往后复制 { *temp_dst++ = *temp_src++; } return dst; } void *memmove (void *dst, void *src, size_t length) { if (NULL == dst || NULL == src) return NULL; char *temp_dst = (char*)dst; char *temp_src = (char*)src; if (temp_src < temp_dst) //从后往前复制 { temp_dst += length - 1; temp_src += length - 1; for (size_t len = 0; len < length; ++len) { *temp_dst-- = *temp_src--; } } else //从前往后复制 { for (size_t len = 0; len < length; ++len) { *temp_dst++ = *temp_src++; } } return dst; }
完整的实现及测试如下:
#include <iostream> using namespace std; void *memcpy (void *dst, void *src, size_t length); void *memmove (void *dst, void *src, size_t length); void *memcpy (void *dst, void *src, size_t length) { if (NULL == dst || NULL == src) return NULL; char *temp_dst = (char*)dst; char *temp_src = (char*)src; for (size_t len = 0; len < length; ++len) //从前往后复制 { *temp_dst++ = *temp_src++; } return dst; } void *memmove (void *dst, void *src, size_t length) { if (NULL == dst || NULL == src) return NULL; char *temp_dst = (char*)dst; char *temp_src = (char*)src; if (temp_src < temp_dst) //从后往前复制 { temp_dst += length - 1; temp_src += length - 1; for (size_t len = 0; len < length; ++len) { *temp_dst-- = *temp_src--; } } else //从前往后复制 { for (size_t len = 0; len < length; ++len) { *temp_dst++ = *temp_src++; } } return dst; } int main () { char a[20] = "Hello joel"; char b[20]; char *p = NULL; p = (char*)memcpy (b, a, 10); while ('\0' != *p) { cout << *p; p++; } cout << "\n"; p = (char*)memmove (a + 1, a, 10); while ('\0' != *p) { cout << *p; p++; } return 0; }
输出结果为:
Hello joel
Hello joel