二.内存函数 上面我们介绍了处理字符串的函数,但是对于其他类型,我们该如何处理呢?通过下面的内存函数的介绍,相信你会有所感悟! 1.内存拷贝函数 a.memcpy 函数原型: 点击加载图片 注意事项: 这里的destination指向要在其中赋值内容的目标数组,source指向要复制的数据源,num是要复制的字节数,注意这里前两个指针的的类型还有函数返回值都是void*,这是因为,memcpy这个函数是内存拷贝函数,它有可能拷贝整型,浮点型,结构体等等各种类型的数据……虽然返回类型是void*,但他也是必不可少的,void*也表示一个地址,用户可以把它强制转换成自己需要的类型去使用。 点击加载图片 点击加载图片 函数的模拟实现: void*my_memcpy(void*dest,constvoid*src,size_tnum){void*ret=dest;assert(dest&&src);//前->后while(num--){*(char*)dest=*(char*)src;dest=(char*)dest+1;src=(char*)src+1;}returnret;} 注意:这里对于(char*)dest不能++或--,因为虽然强制转化类型,但是他的类型实质是没有改变的。 然而,这个函数存在缺陷,就是当对于自己拷贝并且有重叠部分时,会出现bug 如果我们只在一个字符串里操作就会出现问题。例如我想把arr1里的1,2,3,4,5拷贝到3,4,5,6,7上就,理论上arr1[]应该变为1,2,1,2,3,4,5,8,9。 但是实际上: 点击加载图片 为了修改这个bug,大佬们又写出了memmove函数! b.memmove 函数原型和memcpy一样,作用也是一样的,不同的就是可以拷贝自己,并且重叠不会出bug! 为什么之前的模拟实现会出现这个bug呢? 点击加载图片 原因是:当1拷贝到3上时,原来的3已经被1替换,当2拷贝到4上的时候,原来的4已将被2替换。所以当拷贝arr[2]到arr[4]上的时候,原本arr[2]里面存放的3已将被1替换了,同理,所以才得出了不符合我们预期的结果。那如何解决这个问题呢?先来分析这个问题产生的原因,这是因为源空间与目标空间之间有重叠,这里的arr[2]、arr[3]、arr[4]既是源空间也是目标空间,当拷贝1和2的时候把源空间中开没有拷贝的3和4就给覆盖了,此时源空间arr[2]和arr[3]里面存的就不再是3和4了,而是1和2,所以此时拷贝arr[2]和arr[3]里面的数据,其实拷贝的就是1和2。为了解决这个问题,我们可以从后往前拷贝,此时就不会出现这样的问题 但是,我们从后往前拷贝就可以解决这个问题吗?答案是当然不是,比如: 点击加载图片 所以我们需要分类讨论: 点击加载图片 模拟实现: void*my_memmove(void*dest,constvoid*src,size_tnum){void*ret=dest;assert(dest&&src);if(dest 2.内存填充函数——memset 点击加载图片 函数作用: 内存设置 注意事项: 以字节为单位来设置内存中的数据,把从ptr开始往后的num个字节设置成value 形参value也可以是字符,字符其实也是整型,因为字符在内存中存的是其ASCII value如果是整数的话,需要注意它的取值范围,因为一个字节最大可以存储255,超过255就会发生截断 由于这个函数是一个字节一个字节的改变,所以有些初始化是不成立的,比如对于整形数组初始化为1是不可能实现的,因为每个字节都变成01,一个整形事实上是一个很大的数字。所以对于整形数组初始化,一般都是初始化为0或-1.当然对于字符,不必担心,他本身也是一个字符一个字符改变的! 点击加载图片 3.内存比较函数——memcmp 函数原型: 点击加载图片 注意事项: 比较从ptr1和ptr2指针开始的num个字节 两个内存块中不匹配的第一个字节在ptr1中的值低于ptr2中的值返回一个小于零的数子,相等返回零,两个内存块中不匹配的第一个字节在ptr1中的值大于在ptr2中的值返回一个大于零的数子 总结: 本文通过函数使用的介绍来初步学习,函数的模拟实现来深刻理解了库函数的使用。辛苦各位小伙伴们动动小手,三连走一波最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正! |
|