C语言内存函数



🦆 个人主页:深邃-

❄️专栏传送门:《C语言》《数据结构》

🌟Gitee仓库:《C语言》《数据结构》


上个文章,strcpy strncpy 拷贝字符串的,是有局限性的 拷贝一个整型数组呢?结构体数组呢?
接下来就能学到如何拷贝除了字符串以外的类型

目录

memcpy使用和模拟实现

memcpy的概念

c 复制代码
void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。

  • 这个函数在遇到 '\0' 的时候并不会停下来。

  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

  • 头文件#include<string.h>

memcpy的使用

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[10] = { '1','2','3','\0','4','5'};
	char arr2[10] = { '0'};
	memcpy(arr2, arr1, 6);
	return 0;
}


因此可见\0也可以拷贝过来,拷贝的多少只跟num(单位字节)大小有关

c 复制代码
#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//             0 1 2 3 4 5 ...
	int arr2[20] = { 0 };
	//             0 1 2 3 4 5 ...
	//想把arr1中的10个整数,拷贝到arr2中
	//循环遍历
	//memcpy
	memcpy(arr2, arr1, 40);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

memcpy的模拟实现

思路:一个一个字节拷贝过来

c 复制代码
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		src = (char*)src + 1;
		dest = (char*)dest + 1;
	}
	return ret;
}

疑问:为什么已经强制类型转换了,还要再次强转

  • *(char * )dest 里的 (char * ),是一次性的、临时的强制类型转换:它只作用于当前这一次解引用操作,不会修改 dest 这个变量本身的类型

疑问:为什么不能 * (char * )dest ++= * (char * )src++; 这样写:

  • ++ 优先级高于强转,先对void*执行++,就会报错

memmove使用和模拟实现

memmove的概念

memcpy不重叠就行
memmove重叠的和不重叠的都可以(有些编译器实现两者库函数相同,如vs2022)

c 复制代码
void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存快和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove的使用

内存重叠 内存重叠 内存重叠

c 复制代码
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
	//内存重叠
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr+2, arr, 20);

	return 0;
}

memmove的模拟实现

思路:如果dest在src的前面,那么从前向后拷贝是不会重叠的
同理,如果src在dest的前面,那么从后向前拷贝是不会重叠的

c 复制代码
void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src) //1
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else //2 3(包含重合的情况)
	{
		//后->前
		while (num--) //num = 3
		{             
			//num = 2
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

memset函数的使用

memset的使用

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

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

c 复制代码
#include <string.h>
#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "hello world";
	memset(arr+2, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

memset的使用错误

因为memset的是以字节为单位进行修改,一次只更改一个字节

能否将arr的每个元素设置为1

c 复制代码
#include <string.h>
#include <stdio.h>
#include <string.h>
//能否将arr的每个元素设置为1
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memset(arr, 1, 40);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

打印结果 打印结果 打印结果

内存 内存 内存

能否将arr的每个元素设置为0

只有在都改成0的时候才没有问题

cpp 复制代码
#include <string.h>
#include <stdio.h>
#include <string.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memset(arr, 0, 40);
	return 0;
}

memcmp函数的使用

c 复制代码
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 比较从ptr1和ptr2指针指向的位置开始,向后的num个字节
  • 返回值如下:

Return Value

Returns an integral value indicating the relationship between the content of the memory blocks:

return value indicates
<0 the first byte that does not match in both memory blocks has a lower value in ptr1 than in ptr2 (if evaluated as unsigned char values)
0 the contents of both memory blocks are equal
>0 the first byte that does not match in both memory blocks has a greater value in ptr1 than in ptr2 (if evaluated as unsigned char values)

使用 使用 使用

c 复制代码
#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;
}
相关推荐
Chester_19993 小时前
CSP202203C.计算资源调度器
开发语言·数据结构·c++·蓝桥杯
裕晟资质规划4 小时前
武器装备科研生产单位保密资质申请方法论:条件模型与流程拆解
人工智能·算法
EXI-小洲4 小时前
Java 操作 Word:字符串替换、图片插入、动态生成表格与API接口下载
java·开发语言·spring boot·word
会周易的程序员5 小时前
给 PLC 写一个字节码虚拟机:STVM 虚拟机架构设计
开发语言·c++·虚拟机·软plc·iec61131·stvm
机器视觉知识推荐、就业指导5 小时前
为什么老说“纯 Qt 没啥就业市场”?
开发语言·qt
telepan5 小时前
Qt 开发避坑与性能指南:如何优雅、安全地定义全局常量字符串?
开发语言·qt
小灰灰搞电子5 小时前
完全驾驭 Qt 与数据库:C++ ORM 框架 QxOrm 原理与实践指南
数据库·c++·qt
QT界面美化性能优化5 小时前
QT+AI:使用AI技术为QT应用程序赋能
c++·人工智能·qt·opencv·qt教程·qt6.3
m0_695251495 小时前
Qt MaintenanceTool 使用国内镜像加速下载(超详细教程)
开发语言·qt
是隼人6 小时前
buuctf-pwn xdctf2015_pwn200题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门