前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C语言进阶(十) - 内存函数

C语言进阶(十) - 内存函数

作者头像
怠惰的未禾
发布2023-04-27 21:16:09
5000
发布2023-04-27 21:16:09
举报
文章被收录于专栏:Linux之越战越勇

前言

本节了解四个内存相关的函数memcpy、memmove、memcmp、memset

1. memcpy

1.1 memcpy()函数介绍

函数声明

void* memcpy(void* destination, const void* source, size_t num); **头文件是 **<string.h>

作用:把指针souce指向的num个字节复制到指针destination指向的空间。 返回指向目标空间起始地址的指针destination与字符串函数strcpy()不同的是,memcpy适用于任何类型的数据;memcpy不对'\0'进行判断,是否已经复制了num个字节是memcpy所关心的memcpy()函数只要能够实现源空间与目标空间非完全重叠区域的拷贝进行就可以了。如果源空间与目标空间存在重叠区域那么使用memcpy()可能不能正确完成拷贝,从而无法得到正确的结果。因为这是另一个函数memmove()将要完成的功能。

函数原理

从源空间和目标空间的起始位置开始,以字节为单位依次向后复制,直到复制完成。

一个成功拷贝的例子:

代码语言:javascript
复制
//把整型数组arr1中的前20个字节的内容复制到另一个数组arr2中
#include <stdio.h>
#include <string.h>

int main(){
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < 20; i++) {
		printf("%d ", arr2[i]);
	}

	return 0;
}

运行结果:

一个失败拷贝的例子:

//把数组arr1中的前20个字节的内容复制到数组arr1从arr1+2开始的空间中,出现了问题,这是函数实现方法造成的。

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main(){
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[20] = { 0 };
	memcpy(arr1+2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d ", arr2[i]);
	}

	return 0;
}

1.2 模拟实现memcpy()

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>

void* my_memcpy(void* destination, const void* source, size_t num) {
    //断言指针不为空
	assert(destination != NULL && source != NULL);
    //记录目标空间起始地址
	void* start = destination;
    //从前向后依次复制
	while (num--) {
		*(char*)destination = *(char*)source;
		destination = (char*)destination + 1;
		source = (char*)source + 1;
	}
	return start;
}

int main(){
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[20] = { 0 };
	my_memcpy(arr1+2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d ", arr1[i]);
	}

	return 0;
}

2. memmove

2.1 memmove()函数介绍

函数声明

void* memmove(void* destination, const void* source, size_t num); 头文件是<string.h>

作用:把指向源空间的num个字节拷贝到目标空间。 是强化版的memcpy()函数,解决了源空间与目标空间出现部分重叠时拷贝失败的问题。

原理

考虑了拷贝时的重叠问题。

一个例子:

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };

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

运行结果:

2.2 模拟实现memmove()

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>

void* my_memmove(void* destination, const void* source, size_t num) {
	//断言
	assert(destination != NULL && source != NULL);
	void* start = destination;
	if (destination <= source) {
		//前->后
		while (num--) {
			*(char*)destination = *(char*)source;
			destination = (char*)destination + 1;
			source = (char*)source + 1;
		}
	}
	else {
		//后->前
		while (num--) {
			*((char*)destination + num) = *((char*)source + num);
		}
	}
	return start;
}
int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };

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

3. memcmp

3.1 memcmp()函数介绍

函数声明

int memcmp(const void* ptr1, const void* ptr2, size_t num); 头文件<string.h>

作用:比较指针ptr1ptr2指向的空间的前num个数据的大小,是以字节为单位比较的。适用于所有的数据类型。 不关注'\0' 返回一个整数 >0 在两个内存块中不匹配的第一个字节在ptr1中的值低于ptr2中的值 =0 两个内存块的内容相等 <0 在两个内存块中不匹配的第一个字节在ptr1中的值高于ptr2中的值

一个例子:

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[] = { 2,3,4,5,6 };
	int ret = memcmp(arr1, arr2, 10);
	if (ret > 0) {
		printf("arr1 > arr2\n");
	}
	else if (ret == 0) {
		printf("arr1 == arr2\n");
	}
	else {
		printf("arr1 < arr2\n");
	}

	return 0;
}

运行结果:

3.2 模拟实现

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>

int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
	//断言
	assert(ptr1 != NULL && ptr2 != NULL);
	while (num-- && *(char*)ptr1 == *(char*)ptr2) {
		ptr1 = (char*)ptr1 + 1;
		ptr2 = (char*)ptr2 + 1;
	}
	return *(char*)ptr1 - *(char*)ptr2;
}

int main() {
	int arr1[] = { 1,2,3,4,5,6,7,8,9,0 };
	int arr2[] = { 2,3,4,5,6 };
	int ret = my_memcmp(arr1, arr2, 10);
	if (ret > 0) {
		printf("arr1 > arr2\n");
	}
	else if (ret == 0) {
		printf("arr1 == arr2\n");
	}
	else {
		printf("arr1 < arr2\n");
	}

	return 0;
}

4. memset

4.1 memset()函数介绍

函数声明

void* memset(void* ptr, int value, size_t num); 头文件为<string.h>

作用:将ptr所指向的内存块的前num个字节赋值为valuevalue作为int传递,但函数使用该值的unsigned char转换填充内存块返回指针ptr

一个例子:

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main() {
	char str[] = "hell0 world!";
	memset(str + 3, '@', 5);
	puts(str);

	return 0;
}
代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

int main() {
	int arr[20] = { 0 };

	memset(arr , 5, 20);

	return 0;
}

运行结果:

4.2 模拟实现memset()

代码语言:javascript
复制
#include <stdio.h>
#include <assert.h>

void* my_memset(void* ptr, int value, size_t num) {
	//断言
	assert(ptr != NULL);
	while (num--) {
		*((char*)ptr + num) = value;
	}
	
	return ptr;
}
int main() {
	int arr[20] = { 0 };

	my_memset(arr , 5, 20);

	return 0;
}

结语

这篇主要介绍了内存函数的相关概念,并进行了模拟实现。可以较为深入的理解这些函数,并提高熟练程度。


END

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. memcpy
    • 1.1 memcpy()函数介绍
      • 函数声明
      • 函数原理
      • 一个成功拷贝的例子:
      • 一个失败拷贝的例子:
    • 1.2 模拟实现memcpy()
    • 2. memmove
      • 2.1 memmove()函数介绍
        • 函数声明
        • 原理
        • 一个例子:
      • 2.2 模拟实现memmove()
      • 3. memcmp
        • 3.1 memcmp()函数介绍
          • 函数声明
          • 一个例子:
        • 3.2 模拟实现
        • 4. memset
          • 4.1 memset()函数介绍
            • 函数声明
            • 一个例子:
          • 4.2 模拟实现memset()
          • 结语
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档