目录
前言
一:内存拷贝函数
(1)memcpy( )函数
(2)memove( )函数
二:内存比较函数
三:内存设置函数
前言
本文介绍的函数的函数声明都在头文件string.h中。
一:内存拷贝函数
(1)memcpy( )函数
函数声明:void* memcpy(void* dest,const void* src,size_t num)
作用:把一片内存空间的字节拷贝到另一片内存空间。
函数参数的意义:
①dest指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
②src指向要复制的数据源,类型强制转换为 void* 指针。同时我们只是拷贝这一片空间的数据到目标空间而不是修改,所以用const进行修饰。
③num(无符号整型)表示要拷贝的字节数。
函数返回值:
函数调用结束后为了方便我们判断是否拷贝成功,我们把目标地址返回。
调用:
模拟实现的思路:
要一个个字节进行交换,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到
一个字节进行交换,然后继续迭代,通过传入的num来控制循环。
注意:
①*(char*)dest++是不可以的,因为++的优先级大于强制类型转换,对空类型++是非法的。
②*((char*)dest)++在C里面是可以的,但是在C++里面不可以,因为强制转换产生的临时变量在C++里面不能进行++操作。
代码:
//内存拷贝函数(拷贝不重叠)加测试void* my_memcpy(void* dest, const void* src, size_t num){//断言,不能传空指针进来assert(dest && src);//记录目标地址void* ret = dest;while (num--){*(char*)dest = *(char*)src;//对空类型计算是不符合规则的dest = (char*)dest + 1;src = (char*)src + 1;}return ret;}int main(){int arr1[20] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[5] = { 0 };//int类型占4个字节//交换20个字节就是交换数组前5个元素my_memcpy(arr2, arr1, 20);for (int i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;}
(2)memove( )函数
函数声明:void* memove(void* dest,const void* src,size_t num)
作用:用来拷贝重叠的两片内存空间。
函数参数的意义:
①dest指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
②src指向要复制的数据源,类型强制转换为 void* 指针。同时我们只是拷贝这一片空间的数据到目标空间而不是修改,所以用const进行修饰。
③num(无符号整型)表示要拷贝的字节数。
函数返回值:
函数调用结束后为了方便我们判断是否拷贝成功,我们把目标地址返回。
调用:
为什么要把重叠的情况单独拿出来?我们看下面这种情况:
这种目标地址大于源地址的情况,如果要拷贝的数据只有2和3,是没有问题的。
但是如果要拷贝2,3,4,5的话,我们希望的情况的1,2,3,2,3,4,5,8。但实际上我们进行第一次拷贝的时候就已经把4给覆盖掉了。
要防止后面的数据被提前覆盖,我们可以从后面往前拷贝,即先把5赋给7,然后4赋给6,这样就很好的解决了数值被覆盖的问题。
模拟实现的思路:
①进行分类,如果目标地址小于源地址,前向后拷贝;如果目标地址大于或者等于源地址,后向前拷贝。
②一个个字节进行交换,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到
一个字节进行交换,然后继续迭代,通过传入的num来控制循环。
代码:
//内存拷贝函数(重叠)和测试void* my_memmove(void* dest, const void* src, size_t num){//断言,不能传空指针进来assert(dest && src);void* ret = dest;//如果目标地址小于源地址,前向后拷贝if (dest < src){while (num--){*(char*)dest = *(char*)src;//对空类型计算是不符合规则的dest = (char*)dest + 1;src = (char*)src + 1;}}//如果目标地址大于或者等于源地址,后向前拷贝else{while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;}int main(){int arr1[10] = { 0,1,2,3,4,5,6,7,8,9 };//把0,1,2拷贝到3,4,5my_memmove(arr1+4, arr1, 20);for (int i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;}
二:内存比较函数
memcmp( )函数
函数声明:int memcmp(const void* ptr1,const void* ptr2,size_t num)
作用:用来比较两片内存空间,这里的比较不是比较数据,而是一个个字节进行比较,遇到不同的字节就判断大小。
函数参数的意义:
①ptr1和ptr2指向待比较的目标数组,类型强制转换为 void* 指针。同时我们只是比较而不是修改,所以用const进行修饰。
②num(无符号整型)表示要比较的字节数。
函数返回值:
如果两片空间的每一个字节都相同就返回0,如果前面的大就返回大于0的数,前面的小就返回小于0的数。
调用:
模拟实现的思路:
①一个个字节进行比较,用num来控制循环次数。
②如果不相同就直接返回两个字节的差值。
③如果循环结束就代表前num个字节相同,返回0。
代码:
//内存比较函数和测试int my_memcmp(const void* ptr1, const void* ptr2, size_t num){//断言,不能传空指针进来assert(ptr1 && ptr2);while (num--){if (*(char*)ptr1 != *(char*)ptr2)return *(char*)ptr1-*(char*)ptr2;//如果相等,迭代ptr1 = (char*)ptr1 + 1;ptr2 = (char*)ptr2 + 1;}return 0;}int main(){int arr1[10] = { 0,1,2,3,4,5,6,7,8,1 };int arr2[20] = { 0,1,2,3,4,5,6,7,8,10 };int ret = my_memcmp(arr1, arr2, 40);printf("%d ", ret);return 0;}
三:内存设置函数
memset( )函数
函数声明:void* memset(void* ptr,int value,size_t num)
作用:用来初始化内存空间(以字节为单位)。
函数参数的意义:
①ptr指向待初始化的目标数组,类型强制转换为 void* 指针。
②value表示要被设置的值。该值以 int 形式传递,但是函数在填充内存块时是使用该值的无符号字符形式。
重点讲一下value这个参数,要知道我们是对每一个字节进行初始化,一个字节是无法存储像1000这样较大的数据的,这种情况初始化是取1000最后的一个字节进行初始化。
比如传入1000和232初始化的结果是一致的。
③num(无符号整型)表示要初始化的字节数。
函数返回值:
函数调用结束后为了方便我们判断是否初始化成功,我们把目标地址返回。
调用:
模拟实现的思路:
一个个字节进行初始化,我们可以把传过来的指针强行转换为char*类型并进行解引用,拿到
一个字节进行初始化,然后继续迭代,通过传入的num来控制循环。
代码:
//内存设置函数(初始化)void* my_memset(void* ptr, int value, size_t num){//断言,不能传空指针进来assert(ptr);void* ret = ptr;while (num--){*(char*)ptr = value;(char*)ptr = (char*)ptr + 1;}return ret;}int main(){int arr[10] = { 0 };//只认最后一个字节(输入1000和232结果是一样的)my_memset(arr, 232, 40);for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}return 0;}