memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
这个函数的意思是将ptr1中num个字节与ptr2中num个字节进行比较,ptr1大于ptr2则返回大于0的数,相等返回0,小于则返回一个小于0的数。我们先来使用库函数来看看memcmp是怎样工作的吧。
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4,5,6 }; int arr2[] = { 1,2,3,4,6,5 }; int ret = memcmp(arr1, arr2, 16); printf("%d\n",ret); return 0; }
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4,5,6 }; int arr2[] = { 1,2,3,4,6,5 }; int ret = memcmp(arr1, arr2, 20); printf("%d\n",ret); return 0; }
知道库函数memcmp是怎么工作的之后,我们就来自己模拟实现memcmp
模拟实现memcmp
#include<stdio.h> //这里参数的类型为void,能接受任何类型的数据 int my_memcmp(const void* arr1, const void* arr2, size_t num) { //因为不能对void类型的数据直接解引用,所以这里得强制类型转化为 //char*类型,然后一个字节一个字节的操作。 char* str1 = (char*)arr1; char* str2 = (char*)arr2; while (num--) { if (*str1 != *str2) { return *str1 - *str2; } str1++; str2++; } return 0; } int main() { int arr1[] = { 1,2,3,4,5,6 }; int arr2[] = { 1,2,3,4,6,5 }; int ret = my_memcmp(arr1, arr2, 20); printf("%d\n", ret); return 0; }
memcpy
void * memcpy ( void * destination, const void * source, size_t num );
此函数的目的是将从source开始的num个字节的数据拷贝到destination中。先来使用库函数来实现这个功能。
#include<stdio.h> #include<string.h> int main() { int arr1[] = { 1,2,3,4,5,6,5,7,8 }; int arr2[10] = { 0 }; memcpy(arr2, arr1, 6 * sizeof(int)); for (int i = 0; i < 6; i++) { printf("%d ", arr2[i]); } return 0; }
然后就是我们自己来模拟实现memcpy
模拟实现memcpy
#include<stdio.h> void* my_memcpy(void* destination, void* source, size_t num) { char* str1 = (char*)destination; char* str2 = (char*)source; while (num--) { *str1 = *str2; str1++; str2++; } return destination; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8 }; int arr2[10] = { 0 }; my_memcpy(arr2, arr1, 6 * sizeof(int)); for (int i = 0; i < 6; i++) { printf("%d ", arr2[i]); } return 0; }
我们这里看到的是两块没有重叠的部分的拷贝,那么当我们的destination和source有重叠的时候这个memcpy能不能实现呢?我们来看看
#include<stdio.h> void* my_memcpy(void* destination, void* source, size_t num) { char* str1 = (char*)destination; char* str2 = (char*)source; while (num--) { *str1 = *str2; str1++; str2++; } return destination; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8 }; my_memcpy(arr1+2, arr1, 4 * sizeof(int)); for (int i = 0; i < 8; i++) { printf("%d ", arr1[i]); } return 0; }
我们想要得到1,2,1,2,3,4,7,8的结果,可是呢?我们看看运行结果
这里并没有得到我们期待的结果,所以memcpy并不能处理有重叠的情况,那么接下来我要介绍的就可以处理有重叠情况的拷贝了。
memmove
void * memmove ( void * destination, const void * source, size_t num );
这个函数的意思是,从source开始的num个字节移动到从destination开始的num个字节。
还是先来看看库函数是怎样使用的:
#include<stdio.h> #include<string.h> int main() { int arr[6] = { 1,2,3,4,5,6 }; memmove(arr, arr + 2, 4 * sizeof(int)); for (int i = 0; i < 6; i++) { printf("%d ", arr[i]); } return 0; }
当我们来自己实现的时候,我们要想想怎么做?是不是每一次都是从左往右来实现呢?我们来看一个例子:先给一个1-6的数组,然后我们的目的就是想要把1,2,3,4移动到3,4,5,6的位置,最后得到1,2,1,2,3,4,我们就按照从左往右的顺序来移动,看看结果会是怎么样的。
我们先移动1,2
此时原来的3,4的位置已经被改为了1,2,然后我们来继续移动
结果就是这样的,并不能得到我们想要的结果,那么这题应该怎么做呢?我们换个思路,从右往左移动,
那么我们就需要讨论,当需要移动的值跟destination以及后面的num个字节有重叠部分时,当destination>source时,就从右往左移动,相反就从左往右移动 ,当他们没有重叠部分就两种情况都可以,所以为了方便我们就将没有重叠的情况也从右往左移动。
模拟实现memmove
#include<stdio.h> #include<assert.h> void my_memmove(void* destination, void* source, size_t num) { assert(destination && source); char* str1 = (char*)destination; char* str2 = (char*)source; if (str1 > str2 || (str1<str2 && str1+num<str2)) { int tmp1 = num; while (tmp1--) { *(str1 + tmp1) = *(str2 + tmp1); } } else { int tmp2 = num; for (int i = 0; i < tmp2; i++) { *(str1 + i) = *(str2 + i); } } } int main() { int arr[6] = { 1,2,3,4,5,6 }; my_memmove(arr+2, arr, 4 * sizeof(int)); for (int i = 0; i < 6; i++) { printf("%d ", arr[i]); } return 0; }
再来看看另外一种情况是否也能得到结果。
#include<stdio.h> #include<assert.h> void my_memmove(void* destination, void* source, size_t num) { assert(destination && source); char* str1 = (char*)destination; char* str2 = (char*)source; if (str1 > str2 || (str1<str2 && str1+num<str2)) { int tmp1 = num; while (tmp1--) { *(str1 + tmp1) = *(str2 + tmp1); } } else { int tmp2 = num; for (int i = 0; i < tmp2; i++) { *(str1 + i) = *(str2 + i); } } } int main() { int arr[6] = { 1,2,3,4,5,6 }; my_memmove(arr, arr+2, 4 * sizeof(int)); for (int i = 0; i < 6; i++) { printf("%d ", arr[i]); } return 0; }
小结:
那么这些就是我学到的关于内存函数的内容了,感谢大家的观看,如遇错误的地方,欢迎大家指点,我们一起进步。