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语言指针详解-下

相关推荐
Qter_Sean24 分钟前
自己动手写Qt Creator插件
开发语言·qt
何曾参静谧29 分钟前
「QT」文件类 之 QIODevice 输入输出设备类
开发语言·qt
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
小白学大数据3 小时前
Python爬虫开发中的分析与方案制定
开发语言·c++·爬虫·python
冰芒猓4 小时前
SpringMVC数据校验、数据格式化处理、国际化设置
开发语言·maven
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
红中马喽4 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
杜杜的man5 小时前
【go从零单排】Closing Channels通道关闭、Range over Channels
开发语言·后端·golang
java小吕布5 小时前
Java中Properties的使用详解
java·开发语言·后端
versatile_zpc6 小时前
C++初阶:类和对象(上)
开发语言·c++