【内存函数】

目录

  1. memcpy使用和模拟实现
  2. memmove使用和模拟实现
  3. memset使用
  4. memcmp使用

1. memcpy使用和模拟实现

void * memcpy ( void * destination, const void * source, size_t num) ;

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

1.1 使用

c 复制代码
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = { 0 };
memcpy(arr2,arr1,20);

int i = 0;
for (i = 0; i < 10; i++) {
	printf("%d ", arr2[i]);
}

拷贝arr1前5个数到arr2里

输出:

1.2 模拟实现

c 复制代码
void* my_memcpy(void * dest,const void * src,size_t num) {

	void* ret = dest;
	assert(dest);
	assert(src);

	while (num--) {
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}

	return ret;
}

2. memmove使用和模拟实现

void * momove ( void* destination , cosnt void* source , size_t num) ;

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果源空间和目标空间出现重叠,就得用memmove函数处理

2.1 使用

先看下面的代码

c 复制代码
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = { 0 };
my_memcpy(arr1+3,arr1,20);

int i = 0;
for (i = 0; i < 10; i++) {
	printf("%d ", arr1[i]);
}

上面是想从arr1+3,也就是从4开始的位置,复制5个数据,也就是1,2,3,1,2,3,4,5,9,10。但最后的结果却不是这样的,原因就是当到重叠的位置时,数据已经被之前复制的覆盖过了,源数据已经被改变,所以出现错误

输出:

这时换成memove函数试试

c 复制代码
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int arr2[10] = { 0 };
memmove(arr1+3,arr1,20);

int i = 0;
for (i = 0; i < 10; i++) {
	printf("%d ", arr1[i]);
}

输出:

2.2 实现

对于一般的情况,我们直接拷贝数据就行,和memcpy一样。当数据有重叠时,可以分为三种情况

第一种,目标地址desc在源空间src的左边

这种情况下需要拷贝的数据在拷贝之前不会被覆盖,从前往后拷贝

第二种,目标地址desc在src+num中间,这种情况从前向后拷贝时原值会被替换,所以要从后往前拷贝

第三种,目标地址在src的右边,这个时候从左到右拷贝或从右到左都行

c 复制代码
void* my_memmove(void * dest,const void * src,size_t num) {

	assert(dest);
	assert(src);

	void* ret = dest;

	//从前往后拷
	if (dest < src || (char*)dest >= ((char*)src+num)) {

		while (num--) {
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	//从后往前拷
	else {

		dest = (char*)dest + num - 1;
		src = (char*)src + num - 1;

		while (num--) {
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
		
	}

	return ret;
}

3. memeset函数使用

void * memeset ( void * ptr, int value , size_t num) ;

memeset是用来设置内存的,将内存中的值以字节为单位设置为想要的内

c 复制代码
char str[] = "hello world";
memset(str,'x',6);
printf(str);

将字符串的前6个字符改为x

输出:

4. memcmp函数的使用

int memcmp ( cosnt void * ptr1, const void * ptr2, size_t num) ;

  • 比较从ptr1和ptr2开始,向后num个字节的内容
  • 返回值如下:
c 复制代码
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGaOtP12df0";
int n;
n = memcmp(buffer1,buffer2,sizeof(buffer1));

printf("%d ", n);

上面的两个字符串,其中g小写和大写,由于小写的值更大,所以会返回大于0的数

输出:

相关推荐
Zwawa39 分钟前
两根线怎么挂住一堆设备:I2C 协议原理
c语言·单片机·嵌入式
nice_lcj5202 小时前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
紧跟先前的步伐2 小时前
Go AI Agent 实战 28|Agent 的预算、超时与停止条件
开发语言·人工智能·后端·ai·golang
武子康2 小时前
h3.c 的两个权重槽,怎样把内存压力换成 SSD 等待
c语言·人工智能·agent
bksczm3 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
春涧草茶3 小时前
慢就是快16-1协程
开发语言·前端·python
Dovis(誓平步青云)4 小时前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
做科研的周师兄4 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
.痞老板.5 小时前
java ee--计算机是如何工作的
java·开发语言·java-ee
奇树谦5 小时前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构