内存函数主要用于动态分配和管理内存,它直接从指针的方位上进行操作,可以实现字节单位的操作。
其包含的头文件都是:string.h
memcpy
copy block of memory的缩写----拷贝内存块
格式:
void *memcpy(void *dest, const void *src, size_t num);
作用:与strcpy类似,但是从内存的角度从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
要求:
• 这个函数在遇到 '\0' 的时候并不会停下来。也就是说如果在数据中间插入 ‘\0’ 是不会停下复制进程的。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。
• 鉴于拷贝的类型不一,使用*void来表示任意类型。
• num的单位是字节
实例:
int main() { char arr1[20] = "hello world"; char arr2[20] ; memcpy(arr2, arr1,strlen(arr1)+1);//需要复制的字节数为arr1的长度加上字符串结束符'\0' printf("%s", arr2); return 0; }
int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[10] = { 0 }; //将arr1中的4 5 6 7 8,拷贝到arr2中 memcpy(arr2, arr1+3, 5 * sizeof(int));//可以拷贝数组中的任意数据 int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0; }
模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num) { void* ret = dest; while (num--)//根据所要复制的字节数进行递减直到复制完成 { assert(dest && src); *(char*)dest = *(char*)src; dest = (char*)dest+1; src = (char*)src + 1; } return (ret); }
memmove
move block of memory的缩写----内存体转移
格式
void * memmove ( void * destination, const void * source, size_t num );
作用与要求
• 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。 如果源空间和⽬标空间出现重叠,就得使⽤memmove函数处理。由于该特性,实际上memmove比memcpy更加实用,兼容性也更强。
实例:
int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; memmove(arr1 + 2, arr1, 20);//20个字节就是五个整型,在这里arr1+2也就是从3开始拷贝1,2,3,4,5五个数字 int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }//打印出的结果是1,2,1,2,3,4,5,8,9,10(因为arr1的空间只够放下十个整型,并且mommove是允许重叠内存空间的)
模拟实现:
void* my_memmove(void* dest, const void* src, size_t n) { unsigned char* d = (unsigned char*)dest; const unsigned char* s = (const unsigned char*)src; if (s < d && s + n > d) { // 如果源地址在目标地址之前且重叠 for (size_t i = n; i > 0; i--) { d[i - 1] = s[i - 1]; } } else { // 普通情况下的复制 for (size_t i = 0; i < n; i++) { d[i] = s[i]; } } return dest; }
memset
set block of memory的缩写----填充设置内存块
格式
void * memset ( void * ptr, int value, size_t num );
作用:memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。同时在重叠内存空间时实现覆盖原内容。
要求:
• 使用memset
函数时需要谨慎,确保不会意外覆盖原有的数据。
实例:
int main() { char str[] = "almost every programmer should know memset!"; memset(str, '-', 6); printf(str) return 0; }//结果是 ------ every programmer should know memset! //也就是说将almost覆盖
模拟实现:
void* my_memset(void* ptr, int value, size_t num) { unsigned char* p = (unsigned char*)ptr; for (size_t i = 0; i < num; i++) { p[i] = (unsigned char)value; } return ptr; }
memcmp
compare block of memory的缩写----比较内存块
作用:与strcmp类似,⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节,参照下表:
注意:同strcmp不同的是,memcmp可以比较内存区域的大小,具体参照下方实例。
实例:
int main() { char ned1[] = "dsdsdssdds1"; char ned2[] = "dsdsdssdds2"; int n; n = memcmp(ned1, ned2, 44); printf("%d", n); return 0; }
模拟实现:
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {//比较内存区域大小 const unsigned char* p1 = (const unsigned char*)ptr1; const unsigned char* p2 = (const unsigned char*)ptr2; for (size_t i = 0; i < num; i++) { if (p1[i] < p2[i]) return -1; if (p1[i] > p2[i]) return 1; } return 0; }