C语言之详解内存操作函数
创始人
2024-04-08 22:57:52
0

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C/C++】
在这里插入图片描述

目录

  • 前言
  • memcpy
    • 模拟实现
  • memmove
    • 模拟实现
  • memcmp
  • memset

前言

memcpy叫做内存拷贝,memmove叫做内存移动,memcmp叫做内存比较,大家可以想一想为什么要有这些函数呢?我们不是已经由字符串拷贝、字符串比较、字符串追加这些函数了吗?

我们首先知道,所谓的字符串函数:strcpy、strcat、strcmp、strncpy、strncat、strncmp这些函数操作的对象是字符串,或多或少都会跟'\0'打交道。
假设我们现在要操作的是一个数组,比如我们要拷贝整型数组、浮点型数组、又或者是结构体数组,那我们还能不能用strcpy函数来进行拷贝呢?不妨来试一下,请看:
在这里插入图片描述
可以清楚的看到这里会弹出警告⚠。报警告只是一方面,那它能不能把数组arr1中的内存拷贝到数组arr2中去呢?请看调试结果:
在这里插入图片描述
可以看到并没有把数组arr1的内容拷贝到数组arr2中去,**但是数组arr2中的首元素为什么会变成1呢?**我们先来看数组arr1中的1 2 3 4 5在内存中的布局:

当前机器是小端存储
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00

在这里插入图片描述
由此我们可以发现这里用strcpy函数压根就做不到,stycpy的局限性就体现出来了。
由此也出现了内存函数:memcpy、memmove、memcmp、memset

memcpy

memcpy叫做内存拷贝,只要是放到内存中的数据我们都可以进行拷贝。

1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到'\0'的时候并不会停下来。
3.如果source和destination有任何的重叠,复制的结果都是未定义的。

在这之前我们还是要回顾以前的回调函数qsort中的void*-通用类型的指针-无类型指针-即可以接受任意类型的指针
所以,我们来看memcpy函数
的参数:void* memcpy(void * destination, const void * source ,size_t num);这种参数设计的方式与函数strncpy的参数设计方式类似,可以对照学习一下。注意这里参数num的单位是字节。
我们来看举例:
在这里插入图片描述
再来举一个结构体类型的数组,请看举例:
在这里插入图片描述

知道这里我们就大体对函数memcpy的功能有了一定了解,下面我们来模拟实现memcpy函数的功能。

模拟实现

#include
#include
#include
struct S
{char name[20];int age;
};
void* my_memcpy(void* dest, const void* src, size_t num)
{void* ret = dest;assert(dest && src);while (num--){*(char*)dest = *(char*)src;++(char*)dest;++(char*)src;}return ret;
}
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[5] = { 0 };struct S arr3[] = { {"张三",20},{"李四",30} };struct S arr4[3] = { 0 };my_memcpy(arr2, arr1, sizeof(arr1));my_memcpy(arr4, arr3, sizeof(arr3));return 0;
}

然而我们写的这个模拟memcpy函数只能处理内存不重叠的情况;当内存出现重叠时,我们会有专门的函数memmove来处理。

memmove

在这里插入图片描述
所以,memmove函数可以处理这种重叠拷贝的现象。
刚刚说过我们写的my_memcpy函数无法处理重叠拷贝的情况,其实库里的memcpy函数是可以实现重叠拷贝的情况的,请看举例:
在这里插入图片描述
可以看到库里的memcpy函数的确可以处理重叠拷贝的情况,但是我们刚刚写的my_memcpy函数却无法做到,这并不意味的我们✍的这个my_memcpy函数不好。
因为C语言标准规定:memcpy函数只需要能处理不重叠的内存拷贝就可以了。
memmove函数用来处理内存重叠的拷贝。

所以说,我们写的my_memcpy函数刚刚好满足C语言的标准。并没有一些额外的功能。
下面我们来模拟实现memmove函数。

模拟实现

这里涉及到到底是从前向后拷贝还是从后向前拷贝的问题。
在这里插入图片描述
在这里插入图片描述

#include
#include
void* my_memmove(void* dest, const void* src, size_t count)
{void* ret = dest;assert(dest && src);if (dest < src){//前->后while (count--){*(char*)dest = *(char*)src;++(char*)dest;++(char*)src;}}else{//后->前while (count--){*((char*)dest + count) = *((char*)src + count);}}return ret;}
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr + 2, arr, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

在这里插入图片描述
这种写法也可以:

#include
#include
void* my_memmove(void* dest, const void* src, size_t count)
{void* ret = dest;assert(dest && src);if (dest < src||(char*)dest>(char*)src+count){//前->后while (count--){*(char*)dest = *(char*)src;++(char*)dest;++(char*)src;}}else{//后->前while (count--){*((char*)dest + count) = *((char*)src + count);}}return ret;}
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr + 2, arr, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

memcmp

memcmp:int memcmp(const void * ptr1, const void * ptr2, size_t num );(内存比较)

比较从ptr1和ptr2指针开始的num个字节

请看举例:

在这里插入图片描述
说明前8个字节一样。倘若我们要比较前9个字节呢?请看:
在这里插入图片描述
注意是小端存储。

memset

memset—内存设置
memset:void *memset(void *dest,int c,size_t count);
这里的c是你要设置的字符是什么。
这里的count是你要设置多少个字符。

请看举例:
在这里插入图片描述
那我们可不可以这样使用呢?请看:

#include
#include
int main()
{int arr[10] = {0};memset(arr, 1, 10);return 0;
}

上述的代码就是打错特错,千万要记住:memset(arr,1,10),这里的10并不是10个元素的意思,而是10个字节。
如果你非要看一下调试结果,可以🙆‍,请看:
在这里插入图片描述
这是怎么一回事呢?数组arr的大小是40个字节,而这里在40个字节中我们对前10个字节进行更改,而且前十个字节我们改成了1。
即:01 01 01 01 01 01 01 01 01 01 00 00 00 00...
在这里插入图片描述
切记:memset函数可以把一块任何什么数据的空间都可以改,但是它改的单位是字节,我们要改几个字节,每个字节的内容又是什么。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...