[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'.

完。

相关推荐
合方圆~小文1 小时前
架空线路监控系统是针对高压架空输电线路设计的一种安全监测解决方案
c语言·人工智能·硬件工程·数据库架构
序属秋秋秋5 小时前
《数据结构初阶》【八大排序——巅峰决战】
c语言·数据结构·c++·笔记·排序算法
阳光九叶草LXGZXJ6 小时前
达梦数据库-学习-21-C 外部函数
linux·运维·c语言·开发语言·数据库·sql·学习
zyq99101_16 小时前
PTA刷题笔记3(微难,有详解)
c语言·笔记·学习·算法
0xCC说逆向7 小时前
Windows逆向工程提升之IMAGE_IMPORT_DESCRIPTOR
c语言·汇编·windows·安全·逆向·pe结构
在右ZR9 小时前
嵌入式(C语言篇)Day10
c语言
Cherl.16 小时前
探索数据结构的时间与空间复杂度:编程世界的效率密码
c语言·数据结构·算法·时间复杂度·空间复杂度