零基础入门C语言之C语言内存函数

在阅读本篇文章之前,建议读者优先阅读完成本专栏内前面的文章。

目录

前言

一、memcpy函数的使用和模拟实现

二、memmove的使用和模拟实现

三、memset函数的使用

四、memcpy函数的使用

总结


前言

本篇文章主要来介绍与C语言内存函数相关的知识。


一、memcpy函数的使用和模拟实现

我们首先来看一下memcpy函数的函数声明:

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

这个函数实现的功能就是从source位置开始向后复制num个字节的数据到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);
 int i = 0;
 for (i = 0; i < 10; i++)
 {
 printf("%d ", arr2[i]);
 }
 return 0;
}

其运行结果如下:

现在我们来模拟实现一下这个函数,基本的思路就是我们将source的每个字节都复制到destination直到num个字节,那么我们首先需要把这两个指针都强转成char*类型以完成字节级的操作,然后借用循环来完成代码。请读者先思考如何实现,我给出我的示例代码:

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

//模拟实现memcpy函数
void* my_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);
}

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;
}

其运行结果如下:

二、memmove的使用和模拟实现

我们刚才在上面提及到了,memcpy函数是无法处理内存重叠的复制的,而我们如果想实现这个功能,就要去使用memmove函数了,我们首先先看一下它的函数声明:

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

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

其运行结果如下:

下面我们来尝试自行实现一下这个函数。那么它的基本思路是什么呢?我们需要知道有些时候,比如说我们在上面举出的例子,我们需要优先拷贝靠后的元素;而另外一些时候,我们则需要优先拷贝靠前的元素。因此我们解决这个问题的关键就是判断出何时采用何种复制方法。那判断的方法其实也很简单,我们只需要了解哪个指针在左,哪个指针在右即可解决这个问题。接下来请读者先行自己思考,我给出我的示例代码:

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

//模拟实现memmove函数
void* my_memmove(void* dst, const void* src, size_t count)
{
	void* ret = dst;
	if (dst <= src || (char*)dst >= ((char*)src + count)) {
		/*
		* Non-Overlapping Buffers
		* copy from lower addresses to higher addresses
		*/
		while (count--) {
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else {
		/*
		* Overlapping Buffers
		* copy from higher addresses to lower addresses
		*/
		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;
}

其结果如下:

三、memset函数的使用

memset函数是用来设置内存的,它可以将内存中的值以字节为单位设置成我们想要的内容,我们来看看它的函数声明:

cpp 复制代码
void * memset ( void * ptr, int value, size_t num );

这个ptr指向了我们想要操作的内存块位置,value则交代了我们要设置的值,num则代表我们要设置多少个字节为value值。我们键入如下的代码:

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main ()
{
 char str[] = "hello world";
 memset (str,'x',6);
 printf(str);
 return 0;
}

其运行结果如下:

需要注意的是,这个函数是以字节为单位来设置的,也就是说如果我们这么使用的话:

cpp 复制代码
int arr[5] = {0};
memset(arr, 1, 200);

那我们数组中的每个元素0都会出现从第一行到第二行的变化:

cpp 复制代码
00 00 00 00
01 01 01 01

四、memcpy函数的使用

我们专门使用这个函数来比较两个内存,先看看它的函数声明:

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

它会比较从ptr1和ptr2指针指向的位置开始向后的num个字节,然后根据不同的结果给出如下不同的返回值:

我们键入如下的代码:

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main()
{
 char buffer1[] = "DWgaOtP12df0";
 char buffer2[] = "DWGAOTP12DF0";
 int n;
 n = memcmp(buffer1, buffer2, sizeof(buffer1));
 if (n > 0) 
 printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
 else if (n < 0) 
 printf("'%s' is less than '%s'.\n", buffer1, buffer2);
 else
 printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
 return 0;
}

其运行结果如下:


总结

本文介绍了C语言中常用的内存操作函数及其实现方法。重点讲解了memcpy函数的使用与模拟实现,分析了其无法处理内存重叠的局限性;详细说明了memmove函数如何处理重叠内存块的复制,并提供了模拟实现方案;简要介绍了memset函数的内存设置功能和memcmp函数的内存比较功能。通过代码示例演示了这些函数的具体应用场景和实现原理,为理解和掌握C语言内存操作提供了实用参考。

相关推荐
zhmhbest2 小时前
Qt 全球峰会 2025:中国站速递 —— 技术中立,拥抱更大生态
开发语言·qt·系统架构
程序员大雄学编程2 小时前
用Python来学微积分30-微分方程初步
开发语言·python·线性代数·数学·微积分
关于不上作者榜就原神启动那件事2 小时前
模拟算法乒乓球
开发语言·c++·算法
88号技师2 小时前
2025年7月一区SCI优化算法-Logistic-Gauss Circle optimizer-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
再睡一夏就好3 小时前
【C++闯关笔记】unordered_map与unordered_set的底层:哈希表(哈希桶)
开发语言·c++·笔记·学习·哈希算法·散列表
potato_15543 小时前
现代C++核心特性——内存篇
开发语言·c++·学习
lly2024063 小时前
C# 继承
开发语言
August_._3 小时前
【JAVA】基础(一)
java·开发语言·后端·青少年编程
软件开发技术深度爱好者3 小时前
Python类中方法种类介绍
开发语言·python