1.前言
前面学习了关于长度受限制的字符串函数和长度不受限制的字符串函数,其中strcmp对应strncmp函数,strcpy函数对应strncpy函数,strcat函数对应strncat函数,今天我们主要了解的是四个内存函数他们分别是memcpy函数,memmove函数,memset函数,memcmp函数。其中memcpy函数和strcpy函数的功能类似,memcmp函数和strcmp函数类似,接下来就让我们感受一下这些函数的魅力吧。
2 .memcpy函数
对于memcpy函数,有很多人都是第一次接触到,我们进入cplusplus网站cplusplus进行查看memcpy函数的参数。
我们看到函数的参数是void * destination, const void * source, size_t num,对于参数我们需要知道这个函数是有什么功能,它主要就是对任何类型的数据进行拷贝,所以destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:
#include<stdio.h> #include <string.h> int main() { int arr1[10] = { 0 }; int arr2[5] = { 2,3,4,5,6 }; memcpy(arr1, arr2, 20); int i; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
我么运行代码,结果如下:
接下来进行函数的模拟
#include<stdio.h> #include <string.h> void* my_memcpy(void* str1, const void* str2, size_t num) { char* p = (char*)str1; while (num--) { *(char*)str1 = *(char*)str2; str1 = (char*)str1 + 1; str2 = (char*)str2 + 1; } return p; } int main() { int arr1[10] = { 0 }; int arr2[5] = { 2,3,4,5,6 }; my_memcpy(arr1, arr2, 20); int i; for (i = 0; i < 10; i++) { printf("%d ", arr1[i]); } return 0; }
在这里我们需要进行强制转化,转化为char*类型然后一个字节一个字节进行修改,但是这个函数有一定的局限性,当它的目的指针和来源指针指向同一数据且有有重叠部分时函数会出现与预期不同的结果,我们可以简单画一下:
当我们想要把str1拷贝到str2上时当我们拷贝了前三个数据,str1和原来的str2重合时
想要再次进行修改就会出现 重复拷贝,根据c语言的标准memcpy函数是对来自不同数据的进行拷贝,但是对于来自同一数组的需要用另外的一个函数,此函数就是memmove函数接下来我们介绍memmove函数。
3.memmove函数
我们同样进入cplusplus网站查看memmove函数的参数,以及功能
我们看到函数的参数是void * destination, const void * source, size_t num,memmove函数的功能和memcpy函数的功能类似 ,只是memmove是对于来自同一数组的数据进行拷贝,destination和source都是void*类型,因为void*类型可任盛放任何类型的指针,其中destination是指向目标的指针,source是指向来源的指针,num是想要拷贝几个字节,接下来进行代码演示,代码如下:
#include <stdio.h> #include <string.h> int main() { int arr[10] = { 0,1,2,3,4,5,6,7,8,9}; memmove(arr, arr + 3, 20); int i; for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
运行结果如下:
接下啦我们进行memmove函数的模拟实现,代码如下:
#include <stdio.h> #include <string.h> #include <assert.h> void my_memmove(void* str1, const void* str2, size_t sz) { assert(str1 && str2); if (str1 < str2) { while (sz--) { *(char*)str1 = *(char*)str2; str1 = (char*)str1 + 1; str2 = (char*)str2 + 1; } } else { while (sz--) { *((char*)str1 + sz) = *((char*)str2 + sz); } } } int main() { int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; my_memmove(arr+3, arr , 20); int i; for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
在这里我们需要看两种情况,第一种是str1在str2前面
这种情况我们只需从前往后进行赋值即可。对于第二种
str1在str2的后面我们不能从前向后进行拷贝,否则就会出现重复赋值,出现错误,这时我们只需要从后往前进行赋值就可以解决。
4.memset函数
我们进入cplusplus网站进行查阅
memset函数是对数据进行初始化的函数,这个数据可以是任意类型,但是字符串比较适用,ptr是指向想要修改的位置,value是想要修改为什么值,num是修改几个字节,我们直接进入代码演示,代码如下:
#include <stdio.h> #include<string.h> int main() { char arr[] = "abcdefg"; memset(arr, 'x', 4); printf("%s", arr); return 0; }
运行结果如下:
接下来进入我们模拟实现,代码如下:
#include <stdio.h> #include<string.h> #include <assert.h> void* my_memset(void* str, int vaul, size_t sz) { assert(str); char* p = (char*)str; while (sz--) { *(char*)str = vaul; str = (char*)str + 1; } return p; } int main() { char arr[] = "abcdefg"; my_memset(arr, 'x', 4); printf("%s", arr); return 0; }
5.memcmp函数
我们进入cplusplus网站查看函数的参数
memcmp函数的功能就是比较数据的大小,其中num是需要比较的数据的字节数,功能和strncmp类似,我们直接上代码:
#include <stdio.h> #include <string.h> int main() { int arr[5] = { 0,1,2,3,4 }; int arr1[5] = { 0 }; int ret = memcmp(arr, arr1, 5); printf("%d", ret); return 0; }
我们可以理解为
前4个字节相同,第五个字节str1大于str2故返回1。运行结果如下;
接下来进行memcmp函数的模拟实现,代码如下:
#include <stdio.h> #include <string.h> #include <assert.h> int my_memcmp(const void* str1, const void* str2, size_t sz) { assert(str1 && str2); int i; for (i = 0; i < sz; i++) { if (*(char*)str1 >*(char*)str2) { return 1; } else if (*(char*)str1 < *(char*)str2) { return -1; } str1 = (char*)str1 + 1; str2 = (char*)str2 + 1; } return 0; } int main() { int arr[5] = { 0,1,2,3,4 }; int arr1[5] = { 0 }; int ret = my_memcmp(arr, arr1, 5); printf("%d", ret); return 0; }
今天的内容就结束了,希望大家可以学到一些东西。