[C]基础15.C语言内存函数

  • 博客主页:向不悔
  • 本篇专栏:[C]
  • 您的支持,是我的创作动力。

文章目录


0、总结

在C语言中,有一些常用的内存操作函数,它们在处理内存数据时非常实用。下面将详细介绍memcpymemmovememsetmemcmp这四个函数的使用方法及模拟实现。

1、memcpy使用和模拟实现

1.1 memcpy的使用

介绍:

  • 头文件:string.h
  • 函数原型:void* memcpy(void* destination, const void* source, size_t num);
  • 作用:从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memcpy/

总结如下:

  • 源和目标内存块不能重叠,否则会导致未定义行为。
  • 不检查源数据中的终止符,总是复制指定的字节数。
  • 目标内存空间需要足够大以容纳复制的数据,否则会导致内存溢出。

1.2 memcpy的模拟实现

c 复制代码
#include <stdio.h>
#include <assert.h> // 用于 assert

void* my_memcpy(void* dst, const void* src, size_t count) {
	// 保存目标地址,方便最后返回
	void* ret = dst;
	// 断言确保目标和源地址都非空,防止出现空指针异常
	assert(dst != NULL && src != NULL);
	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;
}

思考1:为什么((char*)src)++不行?

  • ((char*)src)++是错误的,因为它试图对一个临时值进行递增操作,导致未定义行为。
  • src = (char*)src + 1;是正确的,因为它先进行类型转换,再进行加法操作,最后将结果赋值给 src,符合C语言的语法规则和逻辑。

思考2 :memcpystrncpy的区别?

  • 操作对象 :memcpy操作的是内存块,按字节复制;strncpy专门用于处理字符串,复制字符直到遇到字符串结束符'\0'或复制完指定数量的字符。
  • 终止条件 :memcpy不检查字符串结束符'\0',严格复制指定字节数;strncpy会在遇到'\0'时停止复制(除非要复制的字符数大于字符串长度)。
  • 安全性 :strncpy在处理字符串时更安全,能避免因未正确处理结束符导致的缓冲区溢出等问题;memcpy若使用不当,容易引发内存越界问题。

2、memmove使用和模拟实现

2.1 memmove的使用

介绍:

2.2 memmove的模拟实现

讲解模拟实现之前,先讲讲while(num--),这个理解很重要。

c 复制代码
#include <stdio.h>

// 主函数
int main() {
	
	int num = 3;
	while (num--) {
		printf("num is now: %d\n", num);
	}
	return 0;
}
c 复制代码
运行:
num is now: 2
num is now: 1
num is now: 0

总结:

  • 当前值用于判断循环条件,然后才减 1。

然后讲解模拟实现:

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

void* my_memmove(void* dst, const void* src, size_t count) {

	assert(dst != NULL && src != NULL);
	void* ret = dst;
	if (dst < src)
	{
		while (count--)
		{
			*(char*)dst = *(char*)src;
			dst = (char*)dst + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (count--)
		{
			*((char*)dst + count) = *((char*)src + count);
		}
	}
	return ret;
}


// 主函数
int main() {

	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//my_memmove(arr1, arr1+2, 20);  // d < s
	my_memmove(arr1 + 4, arr1 + 2, 20);  // d < s

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	printf("hello");
	return 0;
}

总结:在移动过程中,想象目标地址(dst)可以灵活调整位置。在不断比较中清晰掌握目标地址小于源地址(dst < src)和源地址大于目标地址(src > dst)的两种情况。

3、memset函数的使用

3.1 memset的使用

介绍:

3.2 memset的模拟实现

c 复制代码
#include <stdio.h>

void* my_memset(void* ptr, int value, size_t num) {
	unsigned char* p = (unsigned char*)ptr;
	while (num--) {
		*p++ = (unsigned char)value;
	}
	return ptr;
}

// 主函数
int main() {
	char str[] = "almost every programmer should know memset!";
	my_memset(str, '-', 6);
	printf("%s\n", str);
	return 0;
}
c 复制代码
运行:
------ every programmer should know memset!

4、memcmp函数的使用

4.1 memcmp的使用

介绍:

  • 头文件:string.h
  • 函数原型:int memcmp(const void* ptr1, const void* ptr2, size_t num);
  • 作用:比较ptr1ptr2指向的内存块的前num个字节。若相等返回0;若ptr1所指内存大于ptr2,返回正数;否则返回负数。
  • 参考:https://legacy.cplusplus.com/reference/cstring/memcmp/

4.2 memcmp的模拟实现

c 复制代码
#include <stdio.h>

int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
	const unsigned char* p1 = (const unsigned char*)ptr1;
	const unsigned char* p2 = (const unsigned char*)ptr2;
	while (num--) {
		if (*p1 != *p2) {
			return *p1 - *p2;
		}
		p1++;
		p2++;
	}
	return 0;
}

// 主函数
int main() {
	char buffer1[] = "DWgaOtP12df0";
	char buffer2[] = "DWGAOTP12DF0";
	int n = my_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 复制代码
运行:
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.

完。

相关推荐
jz_ddk3 小时前
[学习] C语言数学库函数背后的故事:`double erf(double x)`
c语言·开发语言·学习
无小道5 小时前
c++-引用(包括完美转发,移动构造,万能引用)
c语言·开发语言·汇编·c++
FirstFrost --sy6 小时前
数据结构之二叉树
c语言·数据结构·c++·算法·链表·深度优先·广度优先
森焱森6 小时前
垂起固定翼无人机介绍
c语言·单片机·算法·架构·无人机
秋说8 小时前
【PTA数据结构 | C语言版】两枚硬币
c语言·数据结构·算法
☆璇9 小时前
【数据结构】栈和队列
c语言·数据结构
Heartoxx11 小时前
c语言-指针与一维数组
c语言·开发语言·算法
秋说13 小时前
【PTA数据结构 | C语言版】将数组中元素反转存放
c语言·数据结构·算法
森焱森14 小时前
APM与ChibiOS系统
c语言·单片机·算法·架构·无人机
kyle~15 小时前
C/C++字面量
java·c语言·c++