企业网站建设项目计划书,建立子目录网站,电子商务主要学什么课程,广州市安全教育平台登录目录 前言#xff1a;
一、memcpy 函数的使用及实现
1、memcpy函数的介绍 1.1 memcpy函数参数解读 2、memcpy函数的使用
3、memcpy函数的模拟实现
二、memmove函数的使用及模拟
1、memmove函数的使用
2、memmove函数的模拟实现
三、memset 函数的使用
1、memset函数的…
目录 前言
一、memcpy 函数的使用及实现
1、memcpy函数的介绍 1.1 memcpy函数参数解读 2、memcpy函数的使用
3、memcpy函数的模拟实现
二、memmove函数的使用及模拟
1、memmove函数的使用
2、memmove函数的模拟实现
三、memset 函数的使用
1、memset函数的介绍cplusplus
2、memset函数的使用
2.1 memset函数对数组的应用
2.2 memset函数对字符串的应用
编辑 四、memcmp函数的使用
1、memcmp函数的介绍
2、memcmp函数的使用 前言
上篇文章介绍了C语言字符串函数我们学会了一些对字符串的操作比如说将字符串从一个字符数组拷贝到另一个字符数组中我们可以通过使用strcpy函数实现。但是如果我们想要拷贝一个整型数组到另一个整型数组中时strcpy函数就失效了那我们应该怎么才能实现这个操作呢不要着急本篇文章将带大家搞定这个问题。
一、memcpy函数的使用及实现
1、memcpy函数的介绍 cplusplus上的介绍
作用介绍
参数介绍
返回值介绍 1.1 memcpy函数参数解读
1void* destination
该参数的作用是目标空间用来存放将要拷贝的内存为什么返回值是 void* 呢这是因为这个函数的作用是内存拷贝既然是内存拷贝内存中又可能存放的是整型数组也有可能存放的是字符数组……因此我们不关心存放数据的类型因此使用void*指针来接收任意类型的数据的地址。
2const void* source
source是源头也就是要拷贝的内存数据这里也是void*指针是因为我们不知道我们未来要拷贝的数据是什么类型的可能是整型可能是字符也可能是结构体因此我们也使用void*。
用const修饰是因为我们不希望要拷贝的数据被修改因此使用const修饰会使得整个工程更加稳定。
3size_t num
num的作用是限定拷贝的字节数比如说source中有十个字节的数据我们可以通过修改num的值来拷贝我们想要的个数num为5我们就拷贝五个字节的数据到destination中num的类型是size_t的原因是我们拷贝的个数最低都是0个不会出现负数的情况因此使用size_t类型最为合适。 2、memcpy函数的使用
前面学习了memcpy函数接下来我们将使用memcpy函数来实现一些操作 比如说我们打算将整型数组arr1[ ] {1,2,3,4,5,6,7,8,9,10}拷贝到整型数组 arr2[10] { 0 }; #include stdio.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] { 0 };memcpy(arr2, arr1, 5 * sizeof(int));return 0;
} 调试结果 源头从 3 开始拷贝比如说 #include stdio.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] { 0 };memcpy(arr2, arr12, 5 * sizeof(int));return 0;
} 一些总结 函数memcpy从source的位置开始向后赋值num个字节的数据到destination指向的内容这个函数在遇到\0的时候并不会停下来与字符串函数不同如果source和destination有任何的重叠赋值的结果都是未定义的。 3、memcpy函数的模拟实现
接下来我们尝试自己写一个函数来实现memcpy的功能
void* my_memcpy(void* dest, const void* src, size_t num)
{}
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] { 0 };my_memcpy(arr2, arr1, 5 * sizeof(int));return 0;
}注意在my_memcpy中源头是void*指针类型的
现在有一个问题我们不知道我们要拷贝的是内容是什么类型的我们只知道要拷贝的是20个字节我们该怎么将这20个字节拿到arr2中呢
在前面学习qsort函数的模拟实现中我们用到了一个方法我们可以一个字节一个字节的拷贝那么就可以使用强制类型转换将void*指针转换为char*指针
void* my_memcpy(void* dest, const void* src, size_t num)
{while (num--)//num是字节总数因此num每减1就拷贝一个字节{*(char*)dest *(char*)src;dest (char*)dest 1;src (char*)src 1;}
}
调试结果 总代码
#include stdio.h
void* my_memcpy(void* dest, const void* src, size_t num)
{// 保存目标地址以便最后返回void* ret dest;// 循环 num 次进行逐个字节的复制while (num--){// 将源地址指向的内容复制到目标地址指向的位置并转换为 char* 类型进行操作确保每次只复制一个字节*(char*)dest *(char*)src;// 目标地址向后移动一个字节dest (char*)dest 1;// 源地址向后移动一个字节src (char*)src 1;}// 返回复制后的目标地址return ret;
}
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] { 0 };my_memcpy(arr2, arr1, 5 * sizeof(int));return 0;
}
如果我们向将int arr1[] { 1,2,3,4,5,6,7,8,9,10 };中12345拷贝放到34567的位置上这样可以实现吗 my_memcpy(arr12, arr1, 5 * sizeof(int));
调试结果
为什么这里会是12121呢其实也很好理解 因此最终结果是12121218910
关于重叠问题我们一般使用后面的这个函数memmove函数
而memcpy函数一般用来处理不重叠情况。
在vs2022中memcpy的能力是比较强的也是可以用来处理重叠问题但是对于memcpy函数本来的作用是不包括处理重叠的问题的这就像是老师说让你考到60分就行但是你能考100分。但是不能保证在所有的编译器上memcpy都可以考到100分
也就是说无法确定其它编程环境是否可以实现因此如果要处理重叠问题最好还是交给memmove函数.
二、memmove函数的使用及模拟
1、memmove函数的使用 memove函数的使用与memcpy函数是一样的也是用来实现内存中数据的拷贝的因此就不详细介绍了。不过前面也说了memmove函数可以实现重叠拷贝来测试一下
#include stdio.h
#include string.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };memmove(arr12, arr1, 5 * sizeof(int));return 0;
}
调试结果 可以看到的确将12345的内容拷贝到34567的位置上了
那么memmove函数究竟是怎么实现这个操作的呢我们来模拟了解一下
2、memmove函数的模拟实现 前面我们知道如果拷贝1会把3给覆盖拷贝2会把4给覆盖。
该怎么拷贝才能实现不被覆盖呢
可以从后向前拷贝先拷贝5覆盖7在拷贝4覆盖6这时候在拷贝3覆盖5拷贝2覆盖4拷贝1覆盖3由于345已经拷贝完成不会出现还没有拷贝就被覆盖的情况。 那是不是从后向前拷贝就一定正确呢
我们在换一种情况试试
这时候如果还是从后向前拷贝的话会出现什么问题呢
8拷贝到67拷贝到5这时候向拷贝6的时候已经变成了8因此从后向前失效了。
这时候我们在从前向后拷贝3拷贝到14拷贝到2……恰好可以全部拷贝。 不知道大家有没有发现一个规律 如果dest在src的后面则从后向前拷贝 如果dest在src的前面则从前向后拷贝 如果没有重叠则随意。 如果是 后-前该怎么拷贝呢 比如说先拷贝5我们只需要在起始位置跳过num个字节即可
比如说*((char*)src num)
代码实现
#include stdio.h
#include string.h
void* my_memmove(void* dest, const void* src, size_t num)
{void* ret dest;if (dest src){//前-后while (num--){*(char*)dest *(char*)src;dest (char*)dest 1;src (char*)src 1;}}else{while (num--){//后-前//num进来减1变为19src加上19后跳到最后一位上也就是5dest加上19跳到8的位置然后将5赋值到8的位置*((char*)dest num) *((char*)src num);}}return ret;
}
int main()
{int arr[] { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr2, arr, 5 * sizeof(int));return 0;
}
三、memset函数的使用
1、memset函数的介绍cplusplus 参数介绍注意
memset是以字节为单位来设置内存的 而不是以一个元素为单位设置的。 作用介绍 返回值介绍 2、memset函数的使用
2.1 memset函数对数组的应用
那么memset函数究竟有什么作用呢
比如说
#include stdio.h
int main()
{int arr[10] { 0 };int i 0;for (i 0; i 10; i){arr[i] i 1;}return 0;
}
我们想将arr数组全部初始化为0我们该怎么做呢
你可能会说这不简单直接使用循环不就可以了吗
for (i 0; i 10; i)
{arr[i] 0;
}
这样的确可以不过我们也可以使用库函数memset函数来实现这个操作。
我们要设置的这个空间整型数组arr[10]的地址交给ptr而数组的地址就是数组名arr我们需要将该数组的元素都变为0也就是要设置的值value为0由于是整型数组有十个元素所以num就等于40字节。
代码展示
#include stdio.h
#include string.h
int main()
{int arr[10] { 0 };int i 0;for (i 0; i 10; i){arr[i] i 1;}/*for (i 0; i 10; i){arr[i] 0;}*/memset(arr, 0, 10 * sizeof(int));for (i 0; i 10; i){printf(%d , arr[i]);}return 0;
}调试过程 结果展示 如果memset(arr, 1, 10 * sizeof(int));这是否是将每一个元素都改为1了呢
调试监控窗口 为什么没有达到想要的结果呢
我们在来看一下内存窗口
破案了memset函数将每一个字节都设置为1而不是把一个元素设置为1。
前面强调了memset是以字节为单位来设置内存的 而不是以一个元素为单位设置的。
2.2 memset函数对字符串的应用
代码
#include stdio.h
#include string.h
int main()
{char arr[] hello world;//如何将helo改为五个xmemset(arr, x, 5);return 0;
}调试结果
如果我们想修改world呢
memset(arr6, x, 5);
从前向后数hello五个字符还有一个空格共6个字符。 注意这个函数比较常见因此需要熟练掌握 四、memcmp函数的使用
memcmp函数与之前学习的strcmp函数的功能是比较相似的不过strcmp函数只能用来做字符串的比较而memcmp函数是用来做内存块的比较不论是什么类型。
1、memcmp函数的介绍 参数介绍
返回值介绍 2、memcmp函数的使用
直接上例题比较arr1与arr2中前3个元素
#include stdio.h
#include string.h
int main()
{int arr1[] { 1,2,3,4,5,6,7,8,9,10 };int arr2[] { 1,2,3,3 };int ret memcmp(arr1, arr2, 12);printf(%d\n, ret);return 0;
}
结果 如果我们比较前4个元素呢
int ret memcmp(arr1, arr2, 16);、 这里返回的就是1了。 结语本篇文章到这里就结束啦期待下次的相遇