前言:
内存这个名字我们都不陌生,那么在C语言中内存这个函数是怎么用的呢?今天我们来探究一下C语言中的内存函数。做好笔记。

**功能:内存拷贝(不包含内存重叠)
destination:指针;要拷贝去的地方(目的地)
source:指针;拷贝的内容(原空间)
使用需要包含头文件:string.h
num:拷贝的内存大小(单位为字节)
返回值:返回的是目的地首元素的地址**
有些编译器,memcpy能解决内存重叠的问题,就像我们的 VS 这个编译器,它就能解决内存重叠的问题,在VS中用memcpy来拷贝重叠的问题也可以,只不过不能跨平台使用,想要拷贝内存重叠需要使用我们下面的memmove来解决。

当我们想要用memcpy拷贝自己内存中重叠的问题的时候就会遇到这种问题,当我们想要拷贝前面数字到后面得到时候中间3那个位置就会有冲突。(所以绝大部分编译器在使用memcpy的时候是不会解决重叠的问题)
使用举例:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[10]={0};//创建目的地数组
int arr2[]={1,2,3,4,5,6,7,8,9,10};//创建拷贝的内容
memcpy(arr1,arr2,20);//使用
int i =0;
for(i=0;i<10;i++)//打印
{
printf("%d ",arr1[i]);
}
return 0;
}结果:

memcpy的模拟实现
#include<stdio.h>
#include<assert.h>
//根据memcpy的语法规则模仿memcpy的实现
void* my_memcpy(void*dest,const void*stc,size_t sz)
{
void* ret = dest;
assert(dest&&stc);
while(sz--)
{
*(char*)dest = *(char*)stc;//强制转换为char*类型的,让他每次移动只能移动一个字节
dest = (char*)dest + 1;//强制类型转化是临时的,每次转化完只能在当前的语句使用,不能在另外一条语句里面使用
stc = (char*)stc + 1;
}
return ret ;//返回目标空间的首元素地址
}
int main()
{
int arr1[10]={0};
int arr2[]={1,2,3,4,5,6,7,8,9,10};
my_memcpy(arr1,arr2,20);
int i =0;
for(i=0;i<10;i++)
{
printf("%d ",arr1[i]);
}
return 0;
}结果:


**功能:内存拷贝(包含内存重叠)
destination:指针;要拷贝去的地方(目的地)
source:指针;拷贝的内容(原空间)
使用需要包含头文件:string.h
num:拷贝的内存大小(单位为字节)
返回值:返回的是目的地首元素的地址**
**memmove和memcpy不同的是,memmove是支持重叠问题的,而memcpy不能解决重叠问题
使用举例:**
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[]={1,2,3,4,5,6,6,8,8,9};//创建拷贝的内容
memmove(arr1+2,arr1,0);//使用
int i =0;
for(i=0;i<10;i++)//打印
{
printf("%d ",arr1[i]);
}
return 0;
}结果:

memmove的模拟实现:
分析:
当我们想要拷贝的时候面临着几个问题,就是拷贝同一份内存的时候是向前拷贝还是向后拷贝呢?
分为两种情况:向前和向后拷贝

问题就是将同一份内存拷贝的时候,会发生冲突,会发生拷贝错误。

当dest在 src 左边的时候使用从前向后拷贝,这样拷贝没有问题。

而这种情况的时候就不能从前向后拷贝了,就要从后向前拷贝。也就是当dest在src右边的时候就要从后向前拷贝,才能避免拷贝错误。
模拟实现:
#include<stdio.h>
#include<assert.h>
void* my_memmove(void*dest,const void*src,size_t sz)//模拟标准库memmove设置参数
{
assert(src&&dest);//断言两个指针,防止是空指针
void*str = dest;//存储dest的首地址
if(dest<src)//从前向后拷贝
{
while(sz--)//前向后拷贝和memcpy相同
{
*(char*)dest = *(char*)src;
dest = (char*)dest+1;
src = (char*)src+1;
}
}
else//从后向前拷贝
{
while(sz--)
{
//当我们后向前拷贝的时候,我们就需要让原先的dest的地址先指到dest的末尾,同理src也是这样
//dest和src强制转换为char*类型,加上对应的sz-1就到了这个地址的末尾
//sz-1这个操作在while循环的条件中就已经执行了,所以这里我们只需要+sz就能够到达对应的位置上
*((char*)dest+sz) = *((char*)src+sz);
}
}
return str;
}
int main()
{
int arr1[]={1,2,3,4,5,6,6,8,8,9};//创建拷贝的内容
my_memmove(arr1+2,arr1,20);//使用
int i =0;
for(i=0;i<10;i++)//打印
{
printf("%d ",arr1[i]);
}
return 0;
}结果:


**功能:memset用来设置内存块内容的,将内存中指定长度的内存空间设置为特定的内容
ptr:要被设置的内存块(内存空间),存放了被设置内容的内存空间起始地址
value:想要设置的值,以字节为单位来设置内存块(memset这个函数会将value的值转换为无符号数据来存储)
num:设置多大的内存空间
返回值:返回被设置内存的空间的起始地址**
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "hello world";
char* arr1 = memset(arr,'Q',3);
printf("%s\n",arr);
printf("%s\n",arr);
return 0;
}
结论:
当有⼀块内存空间需要设置内容的时候,就可以使⽤memset函数,值得注意的是memset函数对内存单元的设置是以字节为单位的。

**功能:比较指定内存块的内容,比较的位置从ptr1和ptr2内存首地址开始比较的,比较num个字节
ptr1:要比较的内存块
ptr2:要比较的内存块
num:比较内存块的大小(单位为字节)
返回值:整型(当ptr1大于ptr2的时候返回一个大于0的值,ptr1等于ptr2的时候返回0,ptr1小于ptr2的时候返回一个小于0的值)
同理使用的时候需要包含我们的头文件:string.h**
使用举例:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello world";
char arr2[] = "hello People";
int r = memcmp(arr1,arr2,5);
if(r > 0)
{
printf("arr1>arr2");
}
else if(r<0)
{
printf("arr1<arr2");
}
else
{
printf("arr1 = arr2");
}
return 0;
}结果:

当我们设置不同的值的时候:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello w";
char arr2[] = "hello P";
int r = memcmp(arr1,arr2,7);//为了区分,我们这里改成7个字节
if(r > 0)
{
printf("arr1>arr2");
}
else if(r<0)
{
printf("arr1<arr2");
}
else
{
printf("arr1 = arr2");
}
return 0;
}结果:

另一种情况:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "aaa";
char arr2[] = "bbb";
int r = memcmp(arr1,arr2,3);//为了区分,我们这里改成3个字节
if(r > 0)
{
printf("arr1>arr2");
}
else if(r<0)
{
printf("arr1<arr2");
}
else
{
printf("arr1 = arr2");
}
return 0;
}结果:

总结:
当我们想要比较两个内存的大小的时候我们就可以用C语言中memcmp来进行比较,特点就是可以指定比较长度。
完!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。