C语言部分内存函数详解

C语言部分内存函数详解

前言

在我的C语言-部分字符串函数详解 1-4C语言-部分字符串函数详解 5-10中,函数的操作对象为字符串,如果想处理其他类型的数据,则需用到内存函数

本文将介绍<string.h>头文件下的部分内存函数:

  • 1.memcpy
  • 2.memmove
  • 3.memset
  • 4.memcmp

1.memcpy


函数原型:void * memcpy ( void * destination, const void * source, size_t num );

简介:Copy block of memory------拷贝一块内存

1.1基本用法

会从source向后拷贝num字节的内容至destination

c 复制代码
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
memcpy(arr2, arr1, 5*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:

1.2注意事项

目标空间与原空间不能重叠

如果重叠,拷贝的结果未定义,需使用memmove处理重叠的情况。

在VS2022上,重叠对拷贝结果无影响:

c 复制代码
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr1+3, arr1, 5*sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);

运行结果:

但C语言标准中拷贝的结果未定义,因此仍不建议使用memcpy拷贝有重叠的情况。

目标空间原数据会被覆盖

c 复制代码
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 9,9,9,9,9 };
memcpy(arr2, arr1, 5*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:

目标空间要够大

c 复制代码
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[5];
memcpy(arr2, arr1, 10*sizeof(int));
for (int i = 0; i < 5; i++)printf("%d ", arr2[i]);

运行结果:

VS2022给出了相应的警告:

拷贝字节数需小于原空间大小

c 复制代码
int arr1[5] = { 1,2,3,4,5 };
int arr2[10];
memcpy(arr2, arr1, 10 * sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr2[i]);

运行结果:

VS2022给出了相应的警告:

1.3模拟实现

c 复制代码
void* my_memcpy(void* dst, const void* src, size_t num)
{
	assert(dst && src);
	void* ret = dst;
	while (num--)*((char*)dst)++ = *((char*)src)++;
	return ret;
}

为了处理多种类型的数据,我们传入void*的指针,在强转成char,这样在拷贝时可以按字节依次拷贝。

2.memmove


函数原型:void * memmove ( void * destination, const void * source, size_t num );

简介:Move block of memory------拷贝一块内存

2.1基本用法

memmovememcpy的用法基本一致,且memmove可处理有重叠的空间。

c 复制代码
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 3, arr1, 5 * sizeof(int));
for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);

运行结果:

2.2注意事项

memcpy的基本一致,且memmove可处理有重叠的空间。

2.3模拟实现

memcpy的模拟实现中,我只是单方向的进行拷贝,完成了C语言对memcpy的基本要求。

而在memmove的模拟实现中,如果单方向进行拷贝,会在空间重叠时出现拷贝了新数据的现象,因此需判断拷贝方向。

c 复制代码
void* my_memmove(void* dst, const void* src, size_t num)
{
	assert(dst && src);
	void *ret = dst;
	if (dst < src)
	{
		while (num--)*((char*)dst)++ = *((char*)src)++;
		return ret;
	}
	else
	{
		while (num--)*(((char*)dst) + num) = *(((char*)src) + num);
		return ret;
	}
}

3.memset


函数原型:void * memset ( void * ptr, int value, size_t num );

简介:Fill block of memory------填充内存块

3.1基本用法

按字节设置内存,可用于初始化

c 复制代码
typedef struct Peo
{
	char name[20];
	int age;
	char tele[12];
}Peo;
typedef struct Contact
{
	struct Peo peo[100];
	int num;
}Contact;
int main()
{
	Contact con;
	Contact* p = &con;
	memset(p->peo, 0, sizeof(p->peo));
	return 0;
}

这段代码是我写的通讯录里的。

定义了两个结构体类型 PeoContactPeo 结构体包含姓名、年龄和电话号码。而 Contact 结构体则包含一个 Peo 类型的数组,以及一个整型变量 num,用于记录实际存储了多少个联系人。

main 函数中,首先创建了一个 Contact 类型的变量 con,接着定义了一个指向 Contact 类型的指针 p 并将其指向 con。然后使用 memset 函数将 p->peo 数组中的所有元素初始化为0

初始化效果:

对于 char 类型的数组,这会使它们只包含空字符。

对于 int 类型的成员,这会将它们初始化为0

数组大小:sizeof(p->peo) 返回的是整个 peo 数组的大小,即100个 Peo 结构体的总大小。

4.memcmp


函数原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );

简介:Compare two blocks of memory------比较两个内存块

4.1基本用法

c 复制代码
char ch1[] = "aaaa";
char ch2[] = "aaab";
int n= memcmp(ch1, ch2, 4);
if (n > 0)printf(">");
else if (n < 0)printf("<");
else printf("=");

运行结果:

4.2注意事项

按字节比较

不管什么类型的数据,memcmp都是按字节比较,这使得有时候不能得到预期结果:

c 复制代码
int arr1[10] = { 1 };
int arr2[10] = { 256 };
int n = memcmp(arr1, arr2, 4);
if (n > 0)printf(">");
else if (n < 0)printf("<");
else printf("=");

运行结果:

1肯定比256小,但我们比的规则是逐字节

在小端存储的机器上:
1在内存:

256在内存:

由于是逐字节 比较,所以结果是1>256


希望本篇文章对你有所帮助!

本人仅仅是个C语言初学者,如有任何意见,欢迎各位提出!


相关文章:
C语言指针详解-上
C语言指针详解-下

相关推荐
c4fx12 分钟前
Delphi5利用DLL实现窗体的重用
开发语言·delphi·dll
鸽芷咕35 分钟前
【Python报错已解决】ModuleNotFoundError: No module named ‘paddle‘
开发语言·python·机器学习·bug·paddle
Jhxbdks1 小时前
C语言中的一些小知识(二)
c语言·开发语言·笔记
java6666688881 小时前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言
Violet永存1 小时前
源码分析:LinkedList
java·开发语言
代码雕刻家1 小时前
数据结构-3.1.栈的基本概念
c语言·开发语言·数据结构
Fan_web1 小时前
JavaScript高级——闭包应用-自定义js模块
开发语言·前端·javascript·css·html
梦想科研社1 小时前
【无人机设计与控制】四旋翼无人机俯仰姿态保持模糊PID控制(带说明报告)
开发语言·算法·数学建模·matlab·无人机
风等雨归期1 小时前
【python】【绘制小程序】动态爱心绘制
开发语言·python·小程序
千穹凌帝1 小时前
SpinalHDL之结构(二)
开发语言·前端·fpga开发