C语言内存函数的具体使用

 更新时间:2024年11月05日 11:30:35   作者:爱编程的小新☆  
本文介绍了C语言中几个常用的内存函数,包括memcpy、memmove、memset、memcmp的使用方法及其模拟实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

上期我们学习了字符函数以及字符串函数,但是字符串函数仅仅只能对字符进行操作,那么这次我们来学习一下内存函数

在C语言中内存函数是一组用于内存操作的标准库函数,它们定义在 <string.h>头文件中,这些函数用于复制、设置、比较内存区域等,接下来我们来学习一下C语言中常用的内存函数。

1. memcpy 使⽤和模拟实现

memcpy与strcpy非常相似,但是strcpy只能对字符进行复制操作,而memcpy可以对任意类型的数据进行复制操作。

1.1 memcpy的使用

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

memcpy的使用:

#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);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

运行结果:

可以这里的num参数为20, 表示从 arr1 复制20个字节的数据到 arr2中,因为这里复制的内容为整数,整形的大小占4个字节,所以arr2从arr1中复制了前5个数字(也就是20个字节的数据)

1.2 memcpy模拟实现

既然知道了memcpy函数是如何使用的,那么我们接下来探索一下memcpy是如何实现的

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dst, const void* src, size_t num)
{
	void* ret = dst;
	assert(dst);
	assert(src);
	
	while (num--) {
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}
	return(ret);
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

运行结果:

我们可以看见模拟实现的my_memcpy函数与上面使用的memcpy函数的运行结果是一样的

从中memcpy的前两个形参使用的是void *类型来接收的,void *类型不能进行解引用和加减运算,所以在解引用和加减运算之前需要强制转换成char *类型进行操作

函数的返回值是void*类型,返回的是目标地址,所以在进行指针运算前,我们需要先创建一个指针(ret)存储目标地址,当复制操作完成后,返回目标地址

注意这里的dst和src是指针变量,所以在使用前用assert断言判断一下是否为NULL(空指针),并且因为src指针指向的数据是不能被修改的,所以这里用const进行修饰。

注意:memcpy只负责处理内存不重叠的情况,对于重叠内存拷贝使用memmove

2. memmove 使⽤和模拟实现

memmove函数的参数与memcpy函数是一样的

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

2.1 memmove的使用

#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 ", arr1[i]);
	}
	return 0;
}

运行结果:

那么为什么memmove函数能够处理内存重叠的情况呢?接下来我们来模拟实现一下memmove函数。

2.2 memmove模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_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);
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1 + 2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

memmove的模拟实现与memcpy是相似的,但是这里需要分为两种情况讨论:

1. 目标地址>源内存地址

如果目标地址 > 源内存地址,那么我们就需要将数据从后向前进行拷贝,如果从前向后进行拷贝就会发生下面的现象

当我们从后面向前拷贝就不会出现这种现象:

2. 目标地址<源内存地址

如果目标地址 < 源内存地址,那么我们就需要将数据从前向后进行拷贝

3. 目标地址=源内存地址

当目标地址=源内存地址时,既可以使用从前向后的方式拷贝也可以使用从后向前的方式拷贝。

3. memset 函数的使⽤

memset是⽤来设置内存的,将内存中的值以字节为单位设置成想要的内容。

  • ptr表示更改的起始地址
  • value表示更改的内容
  • num表示更改的字节数

memset的使用:

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

运行结果:

memset函数将str数组中的前6个字节的数据更改成了 ’x‘  

4.memcmp 函数的使用

memcmp是用于比较两块内存
将指针 1 所指内存块的前 num 个字节与指针 2 所指内存块的前num个字节进行比较,如果它们完全匹配,则返回零,否则返回一个不等于零的值,表示哪个更大。

返回值如下:

 memcmp函数的使用:

这里我们比较的是两个整形数组前4个数据的大小, 一个整形的大小为4个字节,所以比较的是16个字节数据的大小,arr前16个字节的数据<arr2前16个字节的数据,所以返回值为-1。

结语

那么以上就是C语言中常用的内存函数,学完内存函数后,对于复制、设置、比较等操作就不仅仅只局限在字符中了,也可以对任意类型的数据进行复制、设置、比较等操作。到此这篇关于C语言内存函数的具体使用的文章就介绍到这了,更多相关C语言内存函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解C++中普通旧数据(POD)的使用

    详解C++中普通旧数据(POD)的使用

    普通旧数据就是内存中的连续字节序列,是能够被“仅当作数据”处理的对象。这篇文章主要带大家了解一下C++中普通旧数据的定义与使用,感兴趣的可以了解下
    2023-03-03
  • C语言原子操作的实现示例

    C语言原子操作的实现示例

    本文主要介绍了C语言中原子操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-12-12
  • C++回调函数的理解和使用教程

    C++回调函数的理解和使用教程

    这篇文章主要给大家介绍了关于C++回调函数的理解和使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 详解C语言常用的一些转换工具函数

    详解C语言常用的一些转换工具函数

    这篇文章主要介绍了C语言常用的一些转换工具函数,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • VisualStudio Community2019在安装的过程中无法进入安装界面的解决方法

    VisualStudio Community2019在安装的过程中无法进入安装界面的解决方法

    这篇文章主要介绍了VisualStudio Community2019在安装的过程中无法进入安装界面的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • Visual Studio2019调试DLL的实现

    Visual Studio2019调试DLL的实现

    本文主要介绍了Visual Studio2019调试DLL的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • C++加密解密php代码的方法

    C++加密解密php代码的方法

    这篇文章主要介绍了C++加密解密php代码的方法,实例分析了基于C++实现加密解密的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • VisualStudio2022编写C语言的实现步骤

    VisualStudio2022编写C语言的实现步骤

    VisualStudio2022是一款强大的集成开发环境,可以用来编写C语言程序,本文主要介绍了VisualStudio2022编写C语言的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • Qt6 QML实现DateTimePicker组件的示例代码

    Qt6 QML实现DateTimePicker组件的示例代码

    本文展示了基于Qt6.10实现的DateTimePicker时间日期选择器组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-12-12
  • 树存储结构的几种表示方法

    树存储结构的几种表示方法

    今天小编就为大家分享一篇关于树存储结构的几种表示方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论