当前位置: 首页 > news >正文

【C语言】memcpy , memset等内存操作函数使用方法与注意事项

这个章节,我们探讨C语言内存操作函数。
重点介绍处理内存操作函数使用和注意事项
和内存函数如何模拟实现。

内存函数所需头文件
#include<string.h>

文章目录

  • memcpy
    • memcpy 函数模拟实现
  • memmove
    • memmove 函数模拟实现
  • memcmp
    • memcmp 函数模拟实现
  • memset
    • memset 函数模拟实现

memcpy

从source的位置开始向后复制num个字节的数据到destination的内存位置

void * memcpy ( void * destination, const void * source, size_t num );
参数说明:

destination: 指向用于存储复制内容的目标数组 。

source: 指向将要复制的数据。

num: 复制的字节个数

返回值:

返回一个指向 destination 首元素地址的指针

注意事项:

  1. 这个函数在遇到 ‘\0’ 的时候并不会停下来。
  2. 如果source和destination有任何的重叠,复制的结果都是未定义的。
  3. 只要处理 不重叠的内存拷贝就可以

函数使用方法:

#include<stdio.h>
#include<string.h>
typedef struct Stu
{
	char nane[20];
	int age;
}T;
int main()
{
	T t[3] = { {"张三",20},{"李四",30},{"小刘",40} };
	T s[4] = { 0 };
	memcpy(s, t, sizeof(t));//把t[3]的内容 拷贝到s里面
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s %d\n", s[i].nane, s[i].age);
	}
	return 0;
}

最终的输出结果:
张三 20
李四 30
小刘 40

memcpy 函数模拟实现

比较num个字节,把他转换成(char*)每次+1转换一个字节,直到转换num个字节。

#include<stdio.h>
#include<string.h>
void* my_memcpy(void* arr1, void* arr2, int num)
{
   assert(arr1 && arr2);
   void* ret = arr1;
   while (num--)
    {
      *((char*)arr1) = *((char*)arr2);
      (char*)arr1 = (char*)arr1 + 1;
      (char*)arr2 = (char*)arr2 + 1;
    }
    return ret;
}

memmove

memmove 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同

void * memmove ( void * destination, const void * source, size_t num );
参数说明:

  1. 指向用于存储复制内容的目标数组 。
  2. source: 指向将要复制的数据
  3. num: 复制的字节个数

返回值:

返回一个指向 destination 首元素地址的指针

注意事项:

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

函数的使用方法:

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

最终的输出结果:
1 2 1 2 3 4 5 8 9

memmove 函数模拟实现

memmove函数的实现分两个部分,因为存在内存覆盖的情况,如果arr2首元素地址大于arr1首元素地址,那肯定需要从前往后拷贝,反之后往前即可。

void* my_memmove(void* arr1, void* arr2, int num)
{
	assert(arr1 && arr2);
	char* ret = arr1;
	if (arr1 < arr2)
	{
		while (num--)
		{
			//从前往后
			*((char*)arr1) = *((char*)arr2);
			(char*)arr1 = (char*)arr1 + 1;
			(char*)arr2 = (char*)arr2 + 1;
		}
	}
	else
	{
		//从后往前
		while (num--)
		{
			*((char*)arr1 + num) = *((char*)arr2 + num);
		}
	}
	return ret;
}

memcmp

内存存储的字节 str1 和 内存存储的字节 str2 的前 num 个字节进行比较

int memcmp(const void *str1, const void *str2, size_t num)
参数说明:

str1: 指向str1内存块的指针
str2: 指向str2内存块的指针
num: 要比较字节的个数

返回值:

  1. str1 大于 str2,则返回大于0的数字
  2. str1 等于str2 ,则返回0
  3. str1 小于 str2,则返回小于0的数字

函数的使用方法:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4};
	int arr2[] = { 1,2,3,5};
	int ret = memcmp(arr1, arr2, 20);
	printf("%d\n", ret);
	return 0;
}

memcmp 函数模拟实现

int my_memcmp(void* arr1, void* arr2, int num)
{
	assert(arr1 && arr2);
	while (*((char*)arr1) == *((char*)arr2) && num--)
	{
		(char*)arr1 = (char*)arr1 + 1;
		(char*)arr2 = (char*)arr2 + 1;
	}
	if (*((char*)arr1) > *((char*)arr2))
	{
		return 1;
	}
	else if (*((char*)arr1) < *((char*)arr2))
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

memset

复制字符 c(一个无符号字符)到参数 str 所指向地址。复制num个字节

void *memset(void *str, int c, size_t num)
参数说明:

str: 指向要复制的的内存块地址
c: 是要被设置的值
num: 要复制多少个字节的个数

返回值:

返回指向srr首元素地址的指针

注意事项:

  1. 不能任意赋值,memset函数是按照字节对内存块进行初始化,如果是int类型的数组,只能初始化0或者-1.
  2. 注意memset,是按字节来复制的,而不是按元素个数,经常有人在这里出错。

函数的使用方法:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	memset(arr, '#', 4);
	printf("%s\n", arr);
	return 0;
}

memset 函数模拟实现

void* my_memset(void* arr, int set, int num)
{
assert(arr);
void* ret = arr;
while (num--)
{
*((char*)arr) = (char)set;
(char*)arr = (char*)arr + 1;
}
return ret;
}

相关文章:

  • Linux版本现状
  • 硬刚ChatGPT!文心一言能否为百度止颓?
  • Python人脸识别
  • Java每日一练(20230313)
  • 【前端】深入浅出缓存原理
  • Vue中实现路由跳转的三种方式详细分解
  • 写给20、21级学生的话
  • IDEA常用插件列表
  • 为什么 Python 没有 main 函数?
  • 我用Python写了一个下载网站所有内容的软件,可见即可下,室友表示非常好用
  • 网络工程师必备知识点
  • 嵌入式软件开发之Linux 用户权限管理
  • 计算机网络面试总结
  • 求最大公约数和最小公倍数---辗转相除法(欧几里得算法)
  • 一文带你吃透操作系统
  • 基于stm32智能语音电梯消毒系统
  • JS中sort()方法返回值?
  • Python雪花代码
  • 蓝桥杯第五天刷题
  • Python打包成exe,文件太大问题解决办法(比保姆级还保姆级)
  • https://app.hackthebox.com/machines/Inject
  • Spring —— Spring简单的读取和存储对象 Ⅱ
  • 渗透测试之冰蝎实战
  • Mybatis、TKMybatis对比
  • Microsoft Office 2019(2022年10月批量许可版)图文教程
  • 《谷粒商城基础篇》分布式基础环境搭建
  • 哈希表题目:砖墙
  • Vue 3.0 选项 生命周期钩子
  • 【车载嵌入式开发】AutoSar架构入门介绍篇
  • 【计算机视觉 | 目标检测】DETR风格的目标检测框架解读