当前位置:网站首页>[Cultivation of internal skills of memory operation functions] memcpy + memmove + memcmp + memset (4)
[Cultivation of internal skills of memory operation functions] memcpy + memmove + memcmp + memset (4)
2022-08-04 22:50:00 【Albert Edison】
文章目录
1. memcpy - 内存拷贝
前面我们学习了 strcpy 和 strncpy,library functions for copying strings,但是,Suppose that we need to copy other types of data?比如 浮点型、整型、结构体 ?
这个时候就引出了 memcpy,It doesn't matter what type of data it is,as long as it is stored in memory,都可以进行拷贝.
函数介绍
void* memcpy(void* dest, const void* src, size_t num);
memcpy 函数是一个用于拷贝两个不相关的内存块的函数.
memcpy 函数会从 src 的位置开始向后复制 num 个字节的数据到 dest 的内存位置,并返回 dest 的首地址.
注意:
1、memcpy 函数在遇到 '\0'
的时候并不会停下来.
2、如果 src 和 dest 有任何的重叠,复制的结果都是未定义的.
3、memcpy When the function is copied,Not sure what data type will be used to copy,所以参数的类型为 void*
(可接收任意类型指针).
代码实现
假设要把 str1 数组中的前 5 个元素拷贝到 str2 中
#include <stdio.h>
#include <string.h>
int main()
{
int str1[] = {
1,2,3,4,5,6,7,8 };
int str2[5] = {
0 };
memcpy(str2, str1, 5 * sizeof(str1[0]));
for (int i = 0; i < 5; i++) {
printf("%d ", str2[i]);
}
return 0;
}
运行结果
模拟实现
假设要把 str1 数组中的后 5 个元素拷贝到 str2 中
进入 my_memcpy 函数体,首先保存 dest 的起始位置,便于之后返回.
然后循环 num 次,每次将 src 中的一个字节的内存数据拷贝到 dest 中的对应位置;
然后 dest 和 src 指针后移继续拷贝,拷贝结束后返回 dest 原来的首地址即可.
在对 dest 和 src 指针进行操作时,要先将它们强制类型转换为char*
类型的指针.
(char*
类型的指针可以向后访问一个字节的内容)
代码实现
#include <assert.h>
#include <stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num) {
assert(dest && src);
void* start = dest;
while (num--) {
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return start;
}
int main()
{
int str1[] = {
1,2,3,4,5,6,7,8,9,10 };
int str2[5] = {
0 };
my_memcpy(str2, str1+5, 5 * sizeof(str1[0]));
for (int i = 0; i < 5; i++) {
printf("%d ", str2[i]);
}
return 0;
}
运行结果
2. memmove - 内存拷贝
memmove 和 memcpy 的作用是一模一样的,But the only difference is memmove 函数处理的源内存块和目标内存块是可以重叠的.
而 memcpy 函数的源内存块和目标内存块是不可以重叠的.
函数介绍
void* memmove(void* dest, const void* src, size_t num);
注意:
1、memmove 函数处理的源内存块和目标内存块是可以重叠的.
2、如果源空间和目标空间出现重叠,就得使用 memmove 函数处理.
代码实现
假设我们要把 str1 数组中的 1、2、3、4、5,拷贝放到 3、4、5、6、7 的位置
#include <stdio.h>
#include <string.h>
int main()
{
int str1[] = {
1,2,3,4,5,6,7,8,9,10 };
memmove(str1 + 2, str1, 20);
for (int i = 0; i < 10; i++) {
printf("%d ", str1[i]);
}
return 0;
}
运行结果
模拟实现
假设我们要把 str1 数组中的 1、2、3、4、5,拷贝放到 3、4、5、6、7 的位置
So how to simulate this??其实很简单,往下看
这种情况是 copy upside down,但是还有一种,假设我们要把 str1 数组中的 3、4、5、6、7 拷贝放到 1、2、3、4、5 的位置
So how to simulate this??其实很简单,往下看
So we're going to categorize,Knowing by drawing,can be divided into three categories;
第一类:当 dest 指针位于 src pointer to the left of the memory block,采用 从前向后 拷贝.
第二类:当 dest 指针位于 src pointer memory block,采用 从后向前 拷贝.
第三类:当 dest 指针位于 src pointer to the right of the memory block,采用 从前向后 和 从后向前 都可以.
**注:**当 dest 指针与 src No copy is required when the pointer is in the same position.
代码实现
#include <assert.h>
#include <stdio.h>
void* my_memmove(void* dest, const void* src, size_t num) {
assert(dest && src);
void* start = 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 start; //返回dest的起始地址
}
int main()
{
int str1[] = {
1,2,3,4,5,6,7,8,9,10 };
my_memmove(str1 + 2, str1, 20);
for (int i = 0; i < 10; i++) {
printf("%d ", str1[i]);
}
return 0;
}
运行结果
3. memcmp - 内存比较
函数介绍
int memcmp(const void* buf1, const void* buf2, size_t count);
memcmp 函数是一个用于比较两个内存块大小的函数.
它会比较从 buf1 和 buf2 指针开始的 count 个字节;
当 buf1 大于 buf2 的时候返回一个 大于0 的数;
当 buf1 等于 buf2 的时候返回 0;
当 buf1 小于 buf2 的时候返回一个 小于0 的数.
代码实现
#include<stdio.h>
#include<string.h>
int main()
{
int str1[] = {
1,2,3,4 };
int str2[] = {
1,2,4,5 };
int ret1 = memcmp(str1, str2, 8);
int ret2 = memcmp(str1, str2, 9);
printf("%d\n", ret1);
printf("%d\n", ret2);
return 0;
}
运行结果
在 VS2019 编译器下,内存采用的是 小端字节序 存储方式,str1 和 str2 在内存中的存储形式如图所示
所以,before comparison 8 bytes,str1 等于 str2,所以返回值为 0;
before comparison 9 bytes,前 8 bytes are equal,第 9 个字节是 str1 小于 str2,所以返回值为 小于0;
4. memset - 内存设置
函数介绍
void *memset( void *dest, int c, size_t count );
memset 函数可以将内存块的某一部分设置为特定的字符.
第一个参数 dest 是开始设置内存的起始位置;
第二个参数 c Is to change the memory set of characters;
第三个参数 count Starting from the starting position need to set the number of bytes of memory.
注意:memset 函数设置内存的时候是一个字节一个字节地设置的.
代码实现
假设我们要把 arr 数组中的前 10 number of bytes is set to 0
#include<stdio.h>
#include<string.h>
int main()
{
int arr[10] = {
1,2,3,4,5,6,7,8,9,10 };
memset(arr, 0, 10);
for (int i = 0; i < 10; ++i) {
printf("%d ", arr[i]);
}
return 0;
}
运行结果
在 VS2019 编译器下,内存采用的是 小端字节序 存储方式,arr1 在内存中的存储形式如图所示
这个和 memcmp is somewhat similar,is to compare byte by byte!
5. 总结
以上就是我们 C Commonly used memory manipulation functions in the language,其实理解起来不难,The important thing is to use more practice
边栏推荐
- 亿流量大考(3):不加机器,如何抗住每天百亿级高并发流量?
- FinClip崁入式搭建生态平台,降低合作门槛
- 【游戏建模模型制作全流程】在ZBrush中雕刻恶魔城男性角色模型
- shell选择结构(if)
- Both synchronized and ReentrantLock are smooth, because they are reentrant locks, and a thread will not deadlock if it takes the lock multiple times. We need reentrant locks
- 地面高度检测/平面提取与检测(Fast Plane Extraction in Organized Point Clouds Using Agglomerative Hierarchical Clu)
- Shell expect 实战案例
- 【TCP/IP 五 ICMP】
- 3D建模师为了让甲方爸爸过稿,还可以这么做,就是在赚血汗钱啊
- temp7777
猜你喜欢
随机推荐
剑指Offer | 数值的整数次方
go语言的time包介绍
边缘检测——(纯享版)
使用cpolar优化树莓派上的网页(2)
DREAMWEAVER8 部分问题解决方案
PHP(3)
typeScript-闭包函数的使用
年薪40W测试工程师成长之路,你在哪个阶段?
质量管理大师爱德华·戴明博士经典的质量管理14条原则
QT 子窗口—>主窗口 信号和槽的交互
基于内容的图像检索系统设计与实现--颜色信息--纹理信息--形状信息--PHASH--SHFT特征点的综合检测项目,包含简易版与完整版的源码及数据!
Jbpm3.2 开发HelloWorld (简单请假流程)客户端
puzzle(022.1)黑白迭代
后排乘客不系安全带?事故瞬间被甩出
中国的顶级黑客在国际上是一个什么样的水平?
被领导拒绝涨薪申请,跳槽后怒涨9.5K,这是我的心路历程
2022精选最新金融银行面试真题——附带答案
【3D建模制作技巧分享】Maya模型如何导入zbrush
PAN3020 Sub-1G无线收发芯片
How to make a video gif?Try this video making gif artifact