C进阶:内存操作函数

内存操作函数

memcpy

头文件:string.h

基本用途:进行不相关(不重叠的内存)拷贝。

函数原型:void* memcpy(void* destination,//指向目标数据的指针

const void* source,//指向被拷贝数据的指针

size_t num);//拷贝的数量(单位:字节)

注:

1.基本原理:从source的位置开始向后复制num个字节的数据到destnation的内存位置。

2.这个函数与strcpy不同,它遇见'\0'的时候并不会停下来。

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

4.void* 之前讲过,为了保证泛用性,使用void*接收任意类型的数据。

使用举例:

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

struct {
	char name[40];
	int age;
}person, person_copy;

int main()
{
	char myname[] = "Pierre de Fermat";
	
	memcpy(person.name, myname, strlen(myname) + 1);
	person.age = 46;

	memcpy(&person_copy, &person, sizeof(person));
	printf("person_copy: %s , %d\n", person_copy.name, person_copy.age);
	return 0;
}

这是将字符串和结构体成员变量拷贝到另一个结构体的举例。

为了更好的理解这一函数,下面我们来模拟实现一下它。

cpp 复制代码
void* my_memcpy(void* dest, const void* src, size_t num)
{
	//断言,防止dest或者src是空指针,如果是空指针则会报错
	assert(dest && src);
	//保存起始地址
	void* ret = dest;
	while (num--)
	{
		//一次用最小单位(字节)移动,保证泛用性
		*(char*)dest = *(char*)src;
		//注:强制类型转换只是临时的,后面+1操作时已不存在
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	//返回目标空间的起始地址
	return ret;
}

memmove

头文件:string.h

基本用途:重叠内存块的拷贝

函数原型:void* memove(void* destnation, const void* source, size_t num)

注:

1.和memcpy的区别就是memove函数处理的源内存块和目标内存块可以重叠。

2.如果原空间和目标空间出现重叠,就得使用memmove函数处理。

使用举例:

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

int main()
{
	char str[] = "memmove can be very useful.....................";
	//将字符串中从第15个元素的位置向后数共11个字符挪到从第20个字符开始向后数第11个元素
	memmove(str + 20, str + 15, 11);
	puts(str);
	return 0;
}

该函数的模拟实现:

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

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	//当目标位置地址小于源内存块数据地址时,采用从前向后拷贝的方式
	if (dest < src)
	{
		//根据字节数量一个一个移动内存单元
		while (num--)
		{
			*(char*)dest = *(char*)src;
			//向后移动一位
			dest = (char*)dest + 1;
			src = (char*)dest + 1;
		}
	}
	//当目标为指针大于源内存块数据地址时,采用从后向前的拷贝方式
	else if (dest > src)
	{
		//将dest和src指针定位到各自最后的内存地址处
		dest = (char*)dest + num - 1;
		src = (char*)src + num - 1;
		//根据字节数量一个一个移动内存单元
		while (num--)
		{
			*(char*)dest = *(char*)src;
			//向前移动一位
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
	}
}

memcmp

头文件:stdio.h

基本用途:顾名思义,与strcmp函数类似,这个函数是比较内存数据大小的(逐字节)。

函数原型:int memcmp(const void* ptr1, const void* ptr2, size_t num);

注:

1.比较从ptr1和ptr2开始的num个字节

2.与strcmp返回值类似,仍是第一个指针内容大于第二个指针的内容,返回大于零的数字,第一个指针内容小于第二个指针的内容,返回小于零的数字,相等,返回零。

基本举例:

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

int main()
{
	char buffer1[] = "axxxxxxxxxxx";
	char buffer2[] = "bbbbbbbbbbbb";

	int n;
	n = memcmp(buffer1, buffer2, sizeof(buffer1));
	printf("%d", n);
	return 0;
}

结果:

这期的博客就分享到这里啦,谢谢各位啦!!!

相关推荐
恋恋西风2 小时前
C++ 理解 std::thread 在单核和多核上的行为差异
开发语言·c++
Brilliantwxx2 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
BizzZ_3 小时前
C++(22)——类型转换和IO流
开发语言·c++
小范同学_3 小时前
JDK1.7 与 JDK1.8 HashMap 底层原理对比 + 数组并发扩容死循环详解
java·开发语言
xiaobobo33303 小时前
c语言中for循环条件中定义临时栈变量的作用域
c语言·for循环条件定义栈变量·大括号作用域·独立栈变量
geovindu3 小时前
CSharp: 万年历
开发语言·后端·c#·.net
我找到地球的支点啦4 小时前
Matlab系列(009) 一CRC循环冗余校验详解
开发语言·数据结构·算法·matlab·信息与通信
予昊4 小时前
从零实现“在线五子棋对战“:WebSocket 实时通信 + 段位匹配
java·开发语言·网络·websocket
惜离殇4 小时前
从零开始的敲代码生活--Linux应用软件(文件操作基础1)
linux·c语言·文件操作·标准io
weixin_461408584 小时前
Mybatis-flex小记
java·开发语言·mybatis