C语言 内存函数

目录

前言

一、memcpy()函数

二、memmove()函数

三、memset函数

四、memcmp()函数

总结


前言

在C语言中内存是我们用来存储数据的地址,今天我们来讲一下C语言中常用的内存函数。


一、memcpy()函数

memcpy()函数与我们之前讲的strcpy()函数类似,只不过memcpy()不单单可以用与字符串的复制,可以复制内存中的各种数据类型。函数语法定义:

cpp 复制代码
void * memcpy ( void * destination, const void * source, size_t num );

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

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
    int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 0 };
    memcpy(arr2, arr1, 20);//20为复制的字节总大小
    int i = 0;
    for (i = 0; i < 10; i++)
 {
       printf("%d ", arr2[i]);
 }
   return 0;
}

虽然memcpy函数也可以实现重叠,但是对于重叠的内存,我们都是交给memmove函数来处理。

函数模拟实现:

cpp 复制代码
void* memcpy(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	assert(dst);
	assert(src);
	/*
	* copy from lower addresses to higher addresses
	*/
	while (count--) {
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return(ret);
}

由于不知道输入的数据类型,我们都是一个字节一个字节开始传输的,所以对地址继续强制类型转换为char *。

二、memmove()函数

memmove函数与上面memcpy函数类似,只不过处理的是重叠的内存。函数语法定义:

cpp 复制代码
void * memmove ( void * destination, const void * source, size_t num );

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

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}


函数的的模拟实现:
有2种情况:
dest在sourc之后

所以我们需要从后往前复制,比如5->7 4->6 3->5 2->4 1->3,这样交换就不会数据丢失。
dest在source之前:

这时我们就要从前往后复制了,比如3->1,4->2,5->3,6->4,7->5,这样就不会覆盖之前的元素了。

cpp 复制代码
void* memmove(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	if (dst <= src || (char*)dst >= ((char*)src + count)) {
		//从前往后复制
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else {
	    //从后往前复制
		dst = (char*)dst + count - 1;
		src = (char*)src + count - 1;
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst - 1;
			src = (char*)src - 1;
		}
	}
	return(ret);
}

三、memset函数

memset()函数的作用时给设置内存的,将内存中的值以字节为单位设置成想要的内容。

函数语法定义:

cpp 复制代码
void * memset ( void * ptr, int value, size_t num );
cpp 复制代码
#include<stdio.h>
#include<string.h>

int main()
{
	char str[] = "hello world";
	memset(str, 'x', 6);
	printf(str);
	return 0;
}


注意:由于 memset是每个字节每个字节进行设置的,所以对于整型元素的设置,可能达不到我们想要的效果。

cpp 复制代码
#include<stdio.h>

int main()
{
	int a[10] = {0};
	memset(a,1,10 );
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d ", a[i]);
	}
	return 0;
}

输出:

我们想把整型数组元素都设置为1,但是结果却不是我们想要的。因为memset函数是每个字节设置的,在数组中的元素在内存中为:

我们发现memset函数是每个字节都设置为1,所以不是我们想要的。

四、memcmp()函数

memcmp函数比较内存中数据大小,函数语法定义:

cpp 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

• 比 较从 ptr1 和 ptr2 指针指向的位置开始,向后的 num 个字节
• 返回值如下:


函数模拟实现:

cpp 复制代码
int my_memcmp(const void* ptr1, const void* ptr2, size_t num){
	assert(ptr1&& ptr2);
	char* p1 = ptr1;
	char* p2 = ptr2;
	size_t count = num;
		while (*p1==*p2)
		{
			if (num == count) {
				break;
			}
			if (*p1 == '\0');
			return 0;
			p1++;
			p2++;
			count++;
		}	
	return *p1 -*p2;
}

总结

上述文章讲了一些与内存有关的函数,希望对你有所帮助。

相关推荐
阿华的代码王国1 分钟前
【JavaEE】——文件IO的应用
开发语言·python
satan–07 分钟前
R语言的下载、安装及环境配置(Rstudio&VSCode)
开发语言·windows·vscode·r语言
电饭叔39 分钟前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student40 分钟前
everyday_question dq20240731
开发语言·arm开发·php
卑微求AC1 小时前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
Yvemil71 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
潘多编程1 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
冷静 包容2 小时前
C语言学习之 没有重复项数字的全排列
c语言·开发语言·学习
碳苯2 小时前
【rCore OS 开源操作系统】Rust 枚举与模式匹配
开发语言·人工智能·后端·rust·操作系统·os