memcpy
void * memcpy ( void * destination, const void * source, size_t num )
- memcpy的作用就是将source的内容拷贝到destination
- num说明了拷贝多少个字节
- 返回值是destination.
memcpy的使用
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[20] = { 0 }; memcpy(arr2, arr1, 20); int i = 0; for (i = 0; i < 5; i++) { printf("%d ", arr2[i]); } return 0; }
memcpy的模拟实现
内存函数就是无论是什么类型的数据都可以使用。
void* ,属于通用类型的指针,可以存放任意类型的地址。
assert,断言,保证dest和source不是空指针。
num是需要拷贝的字节数。
通过将地址转化为(char*)的形式,将需要拷贝的内容一个字节一个字节地将它们拷贝,就可以实现各种数据的拷贝。
然后dest转移到下一个字节,source转移到下一个字节,知道拷贝完num个字节算结束。
#include<stdio.h> #include<assert.h> void* my_memcpy(void* dest, const void* source, size_t num) { assert(dest && source); void* start = dest; while (num--) { *(char*)dest = *(char*) source; dest = (char*)dest + 1; source = (char*)source + 1; } return start; }
memmove
void * memmove ( void * destination, const void * source, size_t num )
- 和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的。
- 参数和memcpy是一样的。
memcpy函数不用来处理重叠的内存的数据拷贝:
将arr1数组改成{1,2,1,2,3,4,5,8,9,10},从第三位元素开始,拷贝自己的第一到第五个元素
#include<stdio.h> #include<assert.h> void* my_memcpy(void* dest, const void* source, size_t num) { assert(dest && source); void* start = dest; while (num--) { *(char*)dest = *(char*) source; dest = (char*)dest + 1; source = (char*)source + 1; } return start; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; my_memcpy(arr1 + 2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
memcpy在重叠内存拷贝的时候,第三个元素被改成1,第四个元素被改成2,
而第五个元素本来是应该赋值为3的,但是第三个元素已经被改成1了。
第六个元素本来是由第四个元素重新赋值,但是第四个元素被改成了2.
memmove的模拟实现
如果说我们要将红色部分拷贝到蓝色部分
从前向后拷贝不行,我们要将红色的部分拷贝到蓝色的部分,先将第一个元素拷贝到第三个元素,红色区域的内存被改变,等到将第三个元素拷贝到第五个元素的时候,第三个元素已经发生改变。
从后向前拷贝,如果我们可以先将第五个元素拷贝到第七个元素,这样红色的三、四、五元素先拷贝完后被改变就可以把数值3,4,5成功传到第五、六、七个元素。
这一次,
从后向前拷贝不行,我们要将红色部分拷贝到蓝色的部分,先将第七个元素拷贝到第五个元素,首先改变了第五个元素的内容,到时候第五个元素还要对第三个元素进行拷贝。
从前向后拷贝,如果我们先将第三个元素拷贝到第一个元素,等轮到第三个元素进行拷贝的时候,第三个元素里的内容已经转出去了,转到第一个元素了,那么第三个元素的内容就可以随便修改了。
总结:
为了保证source中的数据在拷贝之前就被修改,
- 当dest在source的右边的时候,采用从后向前的方式
- 当dest在source的左边的时候,采用从前向后的方式
模拟实现代码
#include<stdio.h> #include<assert.h> void* my_memmove(void* dest, const void* source, size_t num) { assert(dest && source); void* start = dest; if (dest < source) { //从前向后 while (num--) { *(char*)dest = *(char*)source; dest = (char*)dest + 1; source = (char*)source + 1; } } else { //从后向前拷贝 while (num--) { *((char*)dest + num) = *((char*)source + num); } } return start; }
memcmp
可以比较任意类型的数据
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
- ptr1指向的第一个空间
- ptr2指向的第二块空间
- ptr1和ptr2之间的内存比较
- num表示需要比较的字节大小
arr1和arr2比较,arr1比arr2小,返回小于0的数值。
int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 1,3,2 }; int ret = memcmp(arr1, arr2, 12); printf("%d", ret); return 0; }
memset
void * memset ( void * ptr, int value, size_t num )
- ptr需要填充的地址空间
- value,填充什么字符
- num,填充几个字节
#include<stdio.h> #include<string.h> int main() { char arr[] = "hello world"; memset(arr, 'x', 5); printf("%s\n", arr); return 0; }