内存操作函数

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存操作函数相关的知识,希望对你有一定的参考价值。

一.内存操作函数

内存操作函数适用于任何类型,但是它是以字节为单位的。

1.memset函数

  1. 表现形式

在这里插入图片描述
适用于任何类型可以从void *看出。

  1. 作用
    将ptr从第一个开始的num个字节赋值为value。
#include<stdio.h>
#include<string.h>
int main(){
	int arr[10] = { 0 };
	memset(arr, 1, sizeof(arr));//按字节为单位走 数字中的每一位为
	printf("%x\\n", arr[0]);//0000 0001 0000 0001 0000 0001 0000 0001
	return 0;
}

输出:
在这里插入图片描述
上面代码可以证明mem内存函数是以字节为单位的。

2.memcpy函数

  1. 表现形式

在这里插入图片描述
参数为地址。

  1. 作用
    将source按num个字节拷贝到destination中。
    注意:这个函数遇到’\\0’并不会停下来,因为是内存操作。
    但source与destination有重叠的,拷贝得不到想要的结果,函数不起效的,原因在模拟实现中说明。
#include<stdio.h>
#include<string.h>
struct stu{
	char name[20];
	int age;
};

int main(){
	struct stu s1;
	char a[] = "Jimer";
	char *p = memcpy(s1.name, a, strlen(a) +1);//strlen加1是为了将'\\0'拷贝进去。
	printf("%s\\n", s1.name);
	printf("%s\\n", p);
	return 0;
}

输出:
在这里插入图片描述

3.memmove函数

  1. 表现形式
    在这里插入图片描述
    与memcpy相同。
  2. 作用
    也与memcpy相同,但是如果source与destination空间有重叠的地方,这个函数是起效的,可以得到想要的结果。
    用法与memcpy相同。

二.memcpy和memmove的模拟实现

上面说到,memcpy内存重叠时时不起效的,而memmove时起效的入下代码。

#include<stdio.h>
#include<string.h>
int main(){
	char buff[] = "abcdefrt";
	memcpy(buff+1, buff, strlen(buff) + 1);
	memmove(buff+1, buff, strlen(buff) + 1);
	return 0;
}

输出:

memcpy使buff变成了“aaaaaaaa”。
memmove函数使得 buff变成了“aabcdefrt”。
但是由于编译器已经将这一情况修正,所以输出仍然会得到想要的结果。但是我们要知道这种情况。

为什么会出现这种情况呢:
在这里插入图片描述
当第一个替换第二个时,第二个变成了a,第二个替换第三个时,第三个变成了a,如此。memcpy输出为全a,但是memmove出现这种情况时是从后往前拷贝的,这样就不会出现这种情况了。
memcpy模拟实现

#include<stdio.h>
#include<assert.h>
void *Mymemcpy(void* des, void* src, size_t size){
	assert(des);//判断des,src不为NULL。
	assert(src);
	char *_des = (char *)des;//按字节为单位强转成char *
	char *_src = (char *)src;
	while (size--){
		*_des=*_src;
		_des++, _src++;
	}
	return des;
}

int main(){
	char a[] = "abcdefrt";
	char b[] = "asdfgh";
	Mymemcpy(a, a+1, strlen(a)+1);
	Mymemcpy(b+1, b, strlen(b) + 1);//上述内存重叠情况
	printf("%s\\n", a);
	printf("%s\\n", b);
	return 0;
}

输出:
在这里插入图片描述
memmove模拟实现
只是在将上述内存重叠的情况单拎出来,从后往前拷贝。
情况为source首地址比destination首地址大,destination首地址比source尾地址大。

#include<stdio.h>
#include<assert.h>
void *Mymemmove(void* des, void* src, size_t size){
	assert(des);
	assert(src);
	char *_des = (char *)des;//不能放在里面,在外面声明变量
	char *_src = (char *)src;
	if (_src < _des&&_des < (_src + size)){//先判定是哪种情况
		_des += size-1;//指向最后一个元素的起始地址,如果加num指向的是最后一个元素的最后地址。
		_src += size-1;
		while (size--){//从后往前拷贝

			*_des = *_src;
			_des--, _src--;
		}
	}
	else{

		while (size--){//从前往后拷贝
			*_des = *_src;
			_des++, _src++;
		}
	}
	return des;
}

int main(){
	char a[] = "abcdefrt";
	char b[] = "asdfgh";
	Mymemmove(a, a + 1, strlen(a) + 1);
	Mymemmove(b + 1, b, strlen(b) + 1);
	printf("%s\\n", a);
	printf("%s\\n", b);
	system("pause");
	return 0;
}

输出:
在这里插入图片描述

以上是关于内存操作函数的主要内容,如果未能解决你的问题,请参考以下文章

C 中的共享内存代码片段

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

使用导致内存泄漏的音频片段

jQuery的DOM操作

VSCode自定义代码片段——声明函数