网站上的flash怎么做,工程中标公示查询怎么查,企业注册百家号可以做网站吗,网站建设 维护购销合同文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移… 文章目录 1.memcpy使用和模拟实现1.1 memcpy函数的使用规则1.2 memcpy函数的使用1.2 模拟实现memcpy函数 2.memmove 函数的使用和模拟实现2.1 memmove 函数使用规则2.2 memmove函数的使用2.3 模拟实现memmove函数2.3.1 从后往前移2.3.2 从前往后移 2.4 算法实现2.4.1 从前往后移算法实现2.4.2 从后往前移的算法实现2.4.3 最终代码展示及效果 3.memset 函数的使用3.1 memset 函数的使用规则3.2 memset函数的使用3.3 使用memset函数需要注意的地方 4.memcmp 函数的使用4.1 memcpy 函数的使用规则4.2 memcmp函数的使用 5.总结 1.memcpy使用和模拟实现
1.1 memcpy函数的使用规则
它的函数原型如下:
void * memcpy ( void * destination, const void * source, size_t num );具体的函数介绍如下 好相信同学们看了这个函数应该是能够简单了解函数中各个参数的用法。 下面我们来总结一下 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。这个函数在遇到\0的时候并不会停下来。如果source和destintation有任何的重叠复制的结果都是未定义的。 1.2 memcpy函数的使用
好当我们讲了memcpy函数使用规则后来看一下memcpy函数该怎么使用吧~ 代码如下
#include stdio.h
#include string.h
int main() {int arr[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] { 0 };memcpy(arr2, arr,20);//这里的arr2是目标位置arr是起始位置20指的是复制的字节个数int类型占4个字节 那这里的20就相当于5个int类型的元素。//也就是说将arr数组中5个元素拷到arr2数组中arr2是数组首元素的地址也就是说当执行完这个语句arr2数组前5个元素存的是arr1数组前5个元素的值for (int i 0; i sizeof(arr2) / sizeof(arr2[0]); i)//sizeof(arr2)/sizeof(arr2[0])本质上就是用arr2数组所占的总大小/arr2数组中一个元素所占的大小得出的是arr2它数组元素个数{printf(%d , arr2[i]);}return 0;
}代码分析 这里我们用mencpy函数主要是将arr1数组中前5个元素拷到arr2起始地址处。 也就是说这里用memcpy函数进行拷贝的话到时会将arr2数组中前5个元素给覆盖掉。 如图 相信同学们看了这个图以及上面的代码注释是能够理解那个代码逻辑的。 VS运行效果 通过观察 我们发现运行结果确实是符合我们预期的跟我们分析得是一模一样的。 1.2 模拟实现memcpy函数
好刚刚我们讲了memcpy函数的使用那如何模拟实现一个memcpy函数呢 这里想必同学们有点无从下手没事博主这里画个图说不定大家很快就明白了~ 如图 从图中: 假设我们想要把arr中前5个元素拷到arr2数组中第7到第11个元素的位置我们该怎么做呢 在讲解这个之前我们先看一下int类型和char类型在VS编译器中各占几个字节 如图 从运行结果来看 我们可以看出int是占4个字节,char是占1个字节。 有同学可能要问了知道这个有什么用呢 如图 从图中 我们看出memcpy第三个参数就是所要拷贝的字节个数这时我们之前讲的int和char所占的大小就发挥作用了。 因为我们到时要在模拟实现的my_memcpy函数内部中要把数组中int*的元素强转为char*的元素通过所要传的字节数用一个while循环对里面的字节数进行交换。 这里想必同学们会有疑问?为什么要转换为char*的元素进行交换而不转换为其他类型的元素进行字节数的交换呢 这是因为 char*类型每解引用一次访问的是一个字节的内存空间。 如果说我们把目标地址dst和起始地址src转换为其他类型。如short*或int*那么在进行字节的拷贝时可能会跳过一些字节这会导致拷贝结果不正确。 因此我们要将它强制转换为char*,这样就可以保证我们可以正确地访问和拷贝内存中的每个字节。
好当我们分析成这样我们也能画个图把它的思路给分析出来~ 如下
好同学们可以看一下博主总结的思路自己尝试动手写一下这个模拟实现memcpy函数的代码出来。 如果真的写不出来也没关系看一下博主是怎么写这个代码的模仿一下博主的写法。
代码如下
#include stdio.h
#include assert.hvoid* my_memcpy(void* px, void* py, size_t count)//px是指向目标地址而py指针指向源地址这里的count可以理解为交换的字节数有多少
{assert(px py);//用asser判断px和py指针是否为空void* ret px;//这里用指针变量接收px目标位置的地址while (count--)//通过所要交换的字节数从而确立循环的次数{*(char*)px *(char*)py;//将源地址py指向的字节值赋给目标地址px 指向的字节(char*)px (char*)px 1;//px 指针向后移动一个字节(char*)py(char*)py1;//py 指针向后移动一个字节}return ret;//将指针变量ret的地址返回去
}int main() {int arr[] {10,9,8,7,6,5,4,3,2,1 };int arr2[20] { 0 };//针对内存块进行拷贝my_memcpy(arr26, arr, 5 * sizeof(int));//这里的arr26是目标位置也就是说跳过6个元素。arr是源位置 5 * sizeof(int)指的是5个数组元素for (int j 0; j sizeof(arr2) / sizeof(arr2[0]); j)//本质上就是用arr2数组所占的总大小/arr2数组中一个元素所占的大小得出的是arr2它数组元素个数{printf(%d , arr2[j]);}printf(\n);return 0;
}
好相信同学们看了这个代码以及注释是能够理解这个代码逻辑的。
VS运行效果 从运行结果来看 我们发现VS编译器的运行结果是符合我们的预期的也就是说它把arr2数组中的第七个~第十一个元素全都替换为arr数组中前五个元素。 好这个memcpy函数我们就讲到这里希望同学们可以理解同学们要多多实践才行哦~
2.memmove 函数的使用和模拟实现
2.1 memmove 函数使用规则
它的函数原型如下
void * memmove ( void * destination, const void * source, size_t num );具体的函数介绍如下 我们这里就做一个小小地总结吧 memmove函数和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。如果源空间和目标空间出现重叠就得使用memmove函数。 2.2 memmove函数的使用
我们这里直接上代码吧~ 代码如下
#include stdio.h
#include string.h
int main() {int arr1[] { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1 2, arr1, 5 * sizeof(int));//目标地址是arr1跳过两个元素的位置起始地址是arr1首元素的地址5*sizeof(int)指的是5个整型数组中的元素for (int i 0; i sizeof(arr1) / sizeof(arr1[0]); i)//这里本质上就是用arr1数组所占的总大小/arr1数组中一个元素所占的大小得出的是arr1它数组元素个数 {printf(%d , arr1[i]);}printf(\n);return 0;
}VS运行效果: 通过运行结果我们可以看出VS的运行结果是符合我们预期的。 我们这里也简单地给大家画了一个图 如下 从图中 我们把蓝色框住的部分替换为1-5的数值,那有同学可能会问了 这个memmove函数具体是怎么移动的它是怎么做到不覆盖其他元素呢 别急等下博主讲memmove函数模拟实现的时候还会给你细细道来。 2.3 模拟实现memmove函数
好接下来给大家详细讲一下模拟memmove函数的思路~
2.3.1 从后往前移
首先还是老样子我们这里要将目标地址后的5个元素替换为源地址后的5个元素。 如下图 那我们该怎么移红色框住的5个元素到蓝色框住的区域中呢还要避免源字符串src中的5个元素被覆盖。 具体操作如下动图所示 从动图中 大家有没有发现这里我们采取的是从后往前的方法来移动的。 这里我们是先将数组为5的元素移到数组7的位置中再把数组为4的元素移到数组6的位置中以此类推…… 这样子移的目的是避免起始地址src的元素被覆盖如果我们先将数组元素为1移到3的位置中可能把元素为3的数字给覆盖掉这显然是不合理的。因为memmove函数是允许源空间和目标空间出现重叠的。
2.3.2 从前往后移
还是老样子我们这里要将目标地址后的5个元素替换为源地址后的5个元素。 如下 但是这里大家有没有发现这里的起始地址src是高过目标地址dest的因此我们就不能用刚刚的从后往前的方法来移动元素。 我们这里是采用从前往后的方法来移动元素。 具体操作流程如下 从动图中 我们这里是采用从前往后的方法来移动元素。 同理我们这样子移动的目的也是为了避免起始地址中数组元素为6和7在移动过程中被覆盖掉。
2.4 算法实现
好前面我们讲了模拟实现memmmove函数两种移动方法分别是从前往后移和从后往前移的方法。 那具体该如何实现这两种方法的算法呢下面来看一下。
2.4.1 从前往后移算法实现
这里的从前往后移的算法其实跟我们刚刚写的模拟实现memcpy函数的思路其实是差不多的。 为什么这么说呢我们来看一下下面这幅图 通过此图 我们发现memmove函数中的第三个参数是size_t,也就是字节个数。 那我们知道参数num的值那就好办了我们这里可以分别把src指针和dest转换为char*类型的指针对其解引用每解引用一次两个指针各自向后偏移一个元素然后根据参数num的个数来决定所要交换字节的次数。 需要注意的是 这里面我们还要了解一个知识~ 也就是对于相同类型的数组数组元素的地址是按照下标递增的。下标的值越高数组元素的地址就越高。 那同学们可能会有疑问直到这个东西有什么用呢 这是因为我们要在模拟实现memmove函数中加上个if的判断条件这里面就是用来判断什么情况下用从前往后移什么情况下用从后往前移。 那显然 我们这里的起始地址src是打过目标地址dest的。因此那个代码我们就可以这么写~
代码如下 if (dest src)//从前往后移的代码逻辑{while (nums--) {*(char*)dest *(char*)src;(char*)dest (char*)dest 1;(char*)src (char*)src 1;}}else {;//从后往前移的代码逻辑}2.4.2 从后往前移的算法实现
那么同理我们看一下从后往前移的算法该怎么实现。 如下 同样地我们这里还是先观察memmmove的字节个数num这个是关系到我们要交换多少个字节个数。 那么细心的同学可能发现 src指向的是数组首元素的地址也就是1的地址。而dest指向的是数组第三个元素也就是3的地址。 那么我们之前就讲过 要先把起始地址中最后那个元素的字节数与目标地址最后那个元素的字节数进行交换然后每交换一个字节数那个字节数num的值就会-1直到num的值为0,才会停止交换字节数。这样子才不至于说移动的过程中把起始地址中的元素给覆盖掉。 相信同学们看到这里应该是能够把这个代码给写出来的大家可以尝试动手写一下~
好如果同学们写完的话可以看一下自己写的代码和博主写的代码逻辑是否相同~ 代码如下
if (dest src)//从前往后移的代码逻辑
{while (nums--) {*(char*)dest *(char*)src;(char*)dest (char*)dest 1;(char*)src (char*)src 1;}
}
else {;//从后往前移的代码逻辑while (nums--)//每交换一次字节数nums的值都会递减;{*((char*)dest nums) ((char*)src nums);}
}2.4.3 最终代码展示及效果
代码实现
#include stdio.h
#include assert.h
void* my_memmove(void* dest, void* src, int nums) {assert(dest src);void* ret dest;if (dest src)//从前往后移的代码逻辑{while (nums--) {*(char*)dest *(char*)src;(char*)dest (char*)dest 1;(char*)src (char*)src 1;}}else {;//从后往前移的代码逻辑while (nums--)//每交换一次字节数nums的值都会递减;{*((char*)dest nums) *((char*)src nums);}}return ret;
}int main() {int arr[] { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr2, arr, 5 * sizeof(int));//起始地址为数组首元素地址目标地址为数组首元素跳过两个元素的地址交换的是5个int类型的元素也就是20个字节的空间for (int i 0; i 10; i) {printf(%d , arr[i]);}printf(\n);return 0;
}这里面我们分别演示VS从前往后移和从后往前移的运行效果吧~ 1.从前往后移运行效果 从此图 可以看出起始地址src是高过目标地址dest,所以这里是把目标地址中的3~5的元素替换为起始地址中的6-8元素。说明是能够达到我们的预期效果的。 2.从前往后移运行效果 从此图 可以看出目标地址dest是高过起始地址src,所以这里本质上是将目标地址的3~5的元素替换为起始地址中的1~3的元素说明这也是达到我们想要的预期效果。 好这个memmove函数我们就讲到这里这个函数相对比较复杂下来同学们要多去实践这个代码。
3.memset 函数的使用
3.1 memset 函数的使用规则
它的函数原型如下
void *memset (void *ptr,int value,size_t num)具体的函数介绍如下 这里相信同学们看了函数官网的介绍应该是能够理解memset函数的规则我们这里就浅浅总结一下吧~ 总结 memset函数是用来设置内存的将内存中的值以字节为单位设置成想要的内容
3.2 memset函数的使用
代码如下
#include stdio.h
#include string.h
int main() {char arr[] she is my sister!!!;//这里面创建了一个字符数组里面的字符各占一个字节memset(arr, x, 3);//第一个参数是目标地址第二个参数为填充的内存块第三个参数为字节数由于这里第三个字节数为3因此会把前三个字符元素she替换为xprintf(%s\n, arr);//这里从数组中的首元素地址开始往后打印字符串直到遇到\0才停止打印return 0;
}相信同学们看了这个代码的注释自己是应该知道怎么使用这个memset函数的。 VS运行效果 从图中 可以看出VS的运行结果是符合我们的预期的。 3.3 使用memset函数需要注意的地方
这里有同学可能会误用memset函数比如他们可能会把代码写成这样:运行时出现这种情况 如下 他们会有所好奇“为什么打印的不是整数1而是这么大的数呢” 别急这里博主给你讲一下它的原理相信你们很快就懂了~ 如图 我们通过在vs编译器调试时发现,arr数组中的5个元素全都设置都是以01 01 01 01存储的。 这是因为memset函数是以字节单位来设置的它是把每个字节都填充为1而不是说它把一个元素填充为1 我们从vs内存看出它是以十六进制来存储的,因此把这四个01构成一个整数它就是这么一个值。 具体计算过程如下 但是memset函数是可以为任何任意一个数据类型设置内存块来填充的。 那么博主这么讲 就是想告诉同学们memset函数是以字节为单位设置的它会把每个字节填充为memset函数第二个参数那个内存块。所以我们可不敢随意用memset函数把每个元素设置这是做不到的。
好相信讲到这里同学们已经知道memset函数怎么用了那这个memset函数我们就讲到这里
4.memcmp 函数的使用
4.1 memcpy 函数的使用规则
它的函数原型如下
int memcmp ( const void * ptr1, const void * ptr2, size_t num );具体的函数介绍如下 相信同学们看了这个函数官网的介绍应该是知道这个memcmp函数的使用规则的那我们这里就简单总结一下吧~ 比较从ptr1和ptr2指针指向的位置开始向后的num个字节。memcmp函数按照字节顺序比较两个内存块中的字节并返回一个整数值来表示比较结果。 具体规则如下: 如果ptr1的对应字节小于ptr2的对应字节则返回一个负数。如果ptr1的对应字节等于ptr2的对应字节则返回0。如果ptr1的对应字节大于ptr2的对应字节则返回一个正数。 通俗点来讲: 在比较字符串时ASCII 码值就是内存块中对应字符的值。因此可以说memcmp 函数实际上是通过比较两个字符串的 ASCII 码值来判断它们的大小关系。 4.2 memcmp函数的使用
我们这里就简单演示一下memcmp函数用法是怎么样相信同学们看了博主写的这个代码应该是可以上手的~ 代码如下
#include stdio.h
#include string.h
int main()
{char buffer1[] DWgaOtP12df0;//创建两个字符数组buffer1和buffer2char buffer2[] DWGAOTP12DF0;int n memcmp(buffer1, buffer2, sizeof(buffer1));//比较两个字符串相应字符的Ascll码值。由于buffer1第三个字符的Ascll码值大于buffer2第三个字符的Ascll码值因此这里返回一个大于0的数字无需往后比较字符。if (n 0)//因为buffer1buffer2所以会执行这条语句printf(%s is greater than %s.\n, buffer1, buffer2);//%s是从数组首元素开始往后打印字符串直到遇到\0为止else if (n 0)printf(%s is less than %s.\n, buffer1, buffer2);elseprintf(%s is the same as %s.\n, buffer1, buffer2);return 0;
}这个函数跟我们之前讲的strcmp函数非常类似都是比较两个字符数组相应字符的Ascll码值如果出现对应字符的Ascll码值不相同无需往后进行比较。
相信同学们看了博主写的代码注释是可以理解这个代码的。 VS运行效果 分析 由于buffer1数组第三个字符的Ascll码值大于buffer2第三个字符的Ascll码值因此返回的是大于0的数。因此执行的是if(n0)的那条语句。那么从VS运行结果来看它是达到我们的预期效果的。 好这个memcmp函数我们就讲到这里希望同学们可以理解
5.总结
好讲了这么多让我们来回顾今天讲了什么吧~ 函数memcpy主要功能是从起始位置src复制nums个字节的数据到dest指向的内存位置。 但是这个函数遇到\0的时候并不会停下来的。 如图 分析 这里我们是把arr2数组中的10字节的元素用memcpy函数拷到arr数组中那从这个运行结果我们可以看出这个arr数组已经是越界访问了。因此使用这个memcpy函数要小心一点才行。 如果起始地址src和目标地址dest有任何的重叠复制的结果都是未定义的。memmove函数和memcpy函数的功能基本相同也是遇到\0的时候并不会停下来的。 唯一不同的是memmove函数处理的源内存和目标内存块是可以重叠的。 如果说源空间srt和目标空间dest 出现重叠就得使用memmove函数来处理。memset函数是用来设置内存的将内存的值以字节设置成想要的内容。 需要注意的是 memset函数是以字节单位来设置的所以各位同学们要合理使用memset函数否则运行时会输出一个让人意想不到的结果嘿嘿 memcmp函数是比较两个字符数组元素对应的Ascll码值从数组首元素开始往后比较比较nums个字节。如果出现对应字符的Ascll码值不相同无需往后进行比较。 好讲到这里相信同学们对C语言的内存函数有了基本的理解大家看完这篇博客自己下来要多去实践四个函数。唯有这样大家才能把编程学好的
**当然如果大家如果觉得博主这篇文章对你学习C语言有帮助的话可以给博主一键三连吗 ** ** 谢谢大家支持 ** 文章转载自: http://www.morning.nkhdt.cn.gov.cn.nkhdt.cn http://www.morning.skbkq.cn.gov.cn.skbkq.cn http://www.morning.fcrw.cn.gov.cn.fcrw.cn http://www.morning.smmrm.cn.gov.cn.smmrm.cn http://www.morning.rxrw.cn.gov.cn.rxrw.cn http://www.morning.ummpdl.cn.gov.cn.ummpdl.cn http://www.morning.cfocyfa.cn.gov.cn.cfocyfa.cn http://www.morning.hpnhl.cn.gov.cn.hpnhl.cn http://www.morning.dangaw.com.gov.cn.dangaw.com http://www.morning.lsnhs.cn.gov.cn.lsnhs.cn http://www.morning.ynryz.cn.gov.cn.ynryz.cn http://www.morning.fkwgk.cn.gov.cn.fkwgk.cn http://www.morning.ldpjm.cn.gov.cn.ldpjm.cn http://www.morning.rhkgz.cn.gov.cn.rhkgz.cn http://www.morning.xyhql.cn.gov.cn.xyhql.cn http://www.morning.xqltq.cn.gov.cn.xqltq.cn http://www.morning.zsyqg.cn.gov.cn.zsyqg.cn http://www.morning.rlbc.cn.gov.cn.rlbc.cn http://www.morning.lkthj.cn.gov.cn.lkthj.cn http://www.morning.wklhn.cn.gov.cn.wklhn.cn http://www.morning.tmzlt.cn.gov.cn.tmzlt.cn http://www.morning.nfbnl.cn.gov.cn.nfbnl.cn http://www.morning.kdxzy.cn.gov.cn.kdxzy.cn http://www.morning.pmwhj.cn.gov.cn.pmwhj.cn http://www.morning.grzpc.cn.gov.cn.grzpc.cn http://www.morning.hlxpz.cn.gov.cn.hlxpz.cn http://www.morning.dmzfz.cn.gov.cn.dmzfz.cn http://www.morning.bxrqf.cn.gov.cn.bxrqf.cn http://www.morning.ktbjk.cn.gov.cn.ktbjk.cn http://www.morning.xcfmh.cn.gov.cn.xcfmh.cn http://www.morning.dighk.com.gov.cn.dighk.com http://www.morning.lpzqd.cn.gov.cn.lpzqd.cn http://www.morning.mhfbf.cn.gov.cn.mhfbf.cn http://www.morning.pyswr.cn.gov.cn.pyswr.cn http://www.morning.trtxt.cn.gov.cn.trtxt.cn http://www.morning.dwztj.cn.gov.cn.dwztj.cn http://www.morning.jhwwr.cn.gov.cn.jhwwr.cn http://www.morning.rnfn.cn.gov.cn.rnfn.cn http://www.morning.hfxks.cn.gov.cn.hfxks.cn http://www.morning.sfgzx.cn.gov.cn.sfgzx.cn http://www.morning.rbxsk.cn.gov.cn.rbxsk.cn http://www.morning.bhrbr.cn.gov.cn.bhrbr.cn http://www.morning.jzsgn.cn.gov.cn.jzsgn.cn http://www.morning.dyxlj.cn.gov.cn.dyxlj.cn http://www.morning.ljbpk.cn.gov.cn.ljbpk.cn http://www.morning.sltfk.cn.gov.cn.sltfk.cn http://www.morning.htbbp.cn.gov.cn.htbbp.cn http://www.morning.gychx.cn.gov.cn.gychx.cn http://www.morning.zhnpj.cn.gov.cn.zhnpj.cn http://www.morning.ftlgy.cn.gov.cn.ftlgy.cn http://www.morning.rxhs.cn.gov.cn.rxhs.cn http://www.morning.gbrps.cn.gov.cn.gbrps.cn http://www.morning.ffydh.cn.gov.cn.ffydh.cn http://www.morning.bjjrtcsl.com.gov.cn.bjjrtcsl.com http://www.morning.ljjph.cn.gov.cn.ljjph.cn http://www.morning.fswml.cn.gov.cn.fswml.cn http://www.morning.spqtq.cn.gov.cn.spqtq.cn http://www.morning.ptwqf.cn.gov.cn.ptwqf.cn http://www.morning.ngcsh.cn.gov.cn.ngcsh.cn http://www.morning.mtmph.cn.gov.cn.mtmph.cn http://www.morning.fbmjl.cn.gov.cn.fbmjl.cn http://www.morning.dsprl.cn.gov.cn.dsprl.cn http://www.morning.fhghy.cn.gov.cn.fhghy.cn http://www.morning.xlpdm.cn.gov.cn.xlpdm.cn http://www.morning.wmgjq.cn.gov.cn.wmgjq.cn http://www.morning.dbqcw.com.gov.cn.dbqcw.com http://www.morning.dydqh.cn.gov.cn.dydqh.cn http://www.morning.kgtyj.cn.gov.cn.kgtyj.cn http://www.morning.wlqbr.cn.gov.cn.wlqbr.cn http://www.morning.bfjyp.cn.gov.cn.bfjyp.cn http://www.morning.fy974.cn.gov.cn.fy974.cn http://www.morning.rbbzn.cn.gov.cn.rbbzn.cn http://www.morning.mcwgn.cn.gov.cn.mcwgn.cn http://www.morning.gzzxlp.com.gov.cn.gzzxlp.com http://www.morning.ygkb.cn.gov.cn.ygkb.cn http://www.morning.xsctd.cn.gov.cn.xsctd.cn http://www.morning.rcklc.cn.gov.cn.rcklc.cn http://www.morning.wyctq.cn.gov.cn.wyctq.cn http://www.morning.rzscb.cn.gov.cn.rzscb.cn http://www.morning.pjwml.cn.gov.cn.pjwml.cn