C语言内存函数

devtools/2024/9/24 22:35:18/

C语言内存函数

个人主页:大白的编程日记
个人专栏:大白的编程日记


文章目录

  • C语言内存函数
    • 前言
    • 一.memcpy函数
      • 1.1memcpy函数的使用
      • 1.2memcpy的模拟实现
    • 二.memmove
      • 2.1memmove的使用
      • 2.2memmove的模拟实现
    • 三.memse函数的使用
      • 3.1memset的使用
      • 3.2memset的模拟实现
    • 四.memcmp函数
      • 4.1memcmp函数的使用
      • 4.2memcmp的模拟实现
    • 后言

前言

哈喽,各位小伙伴大家好。今天小编给大家带来的是C语言内存函数内容的分享。话不多说,咱们进入正题!向大厂冲锋!

一.memcpy函数

1.1memcpy函数的使用

void * memcpy ( void * destination, const void * source, size_t num );

memcpy函数是用来拷贝内存的函数。
函数有三个参数分别是 destination source num。
分别代表 拷贝目的地指针 拷贝源头指针 拷贝长度。
那具体是如何使用的呢?

  • 具体功能
    函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。注意num的单位是字节。

  • 拷贝长度
    这个函数在遇到 ‘\0’ 的时候并不会停下来。只会根据num的指定的长度拷贝内存,单位是字节。

  • 重叠问题
    如果source和destination有任何的重叠,复制的结果都是未定义的。内存重叠的情况不适合用memcpy拷贝。

  • 头文件
    memcpy需要包含头文件string.h,不止memcpy,所有内存函数都需要包含头文件string.h。

  • 对比strcpy
    memcpy因为是拷贝内存,所以不会关心拷贝的类型。任何存储在内存中类型的数据都能拷贝。而strcpy只能用来拷贝字符串。

例如拷贝整型时:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };memcpy(arr2, arr1, 20);//20个字节==5个整型int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}


注意这里的20是20个字节,不是整形。
4*5==20。所以拷贝的是5个整型。
所以memcpy的功能其实包含了strcpy。


1.2memcpy的模拟实现

接下来我们来模拟实现memcpy函数。
因为是拷贝内存,所以我们直接根据num的长度,将源头souce指向的内存字节的内容拷贝到destination指向的内存字节即可。
每次拷贝后指针向后souce和destination指针向后移动,继续拷贝。

  • 图解:

void* my_memcpy(void* dst, const void* src, size_t count)
{void* ret = dst;//保存目的地起始地址assert(dst);assert(src);//断言while (count--) {*(char*)dst = *(char*)src;//拷贝dst = (char*)dst + 1;src = (char*)src + 1;//移动}return(ret);//返回目的地
}

这里为了能拷贝任意类型的数据,我们用void接收和返回。
然后断言一下,确保不会对空指针解引用。然后我们强转成char
的指针在拷贝,确保能访问到每个字节,可以拷贝任意长度的内存。
我们再拷贝前先保留了目的地的起始地址,防止丢失。

	(char*)dst++;(char*)src++;//移动

那我们移动可不可以写成这样呢?
不行,因为这样的强转是临时的。
如果要写的话应该写成这样

    ((char*)dst)++;((char*)src)++;//移动

二.memmove

2.1memmove的使用

前面我们说memcpy不能拷贝内存重叠的情况。
那内存重叠的情况怎么拷贝呢?这时候就需要memmove函数了。

void * memmove ( void * destination, const void * source, size_t num );

memmove函数的参数和返回值与memcpy一样。

  • 对比memcpy
    和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

  • 功能
    如果源空间和目标空间出现重叠,就得使用memmove函数处理。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1 + 2, arr1, 20);//内存重叠int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}

我们从arr1向后拷贝5个元素到arr1+2的位置。存在内存重叠。
在这里插入图片描述

2.2memmove的模拟实现

这里我们是不是还是跟memcpy一样一个一个从源头拷贝到目的地就可以了呢?

void* my_memcpy(void* dst, const void* src, size_t count)
{void* ret = dst;//保存目的地起始地址assert(dst);assert(src);//断言while (count--) {*(char*)dst = *(char*)src;//拷贝dst = (char*)dst + 1;src = (char*)src + 1;//移动}return(ret);//返回目的地
}

  • 验证

    这里我们需要对src和dst的位置进行分类讨论。
    当有重叠情况时:

  • src在dst前面

    如果src在dst前面,我们就从后往前拷贝。

  • src在dst后面

    如果src在dst前面,我们就从前往后拷贝。

void* my_memmove(void* dst, void* src, size_t num)
{void* ret = dst;assert(dst && src);if (src > dst)//比较的是地址{//前——>后while(num--){*(char*)dst = *(char*)src;dst = (char*)dst + 1;src = (char*)src + 1;}}else{//从后往前while (num--)//循环{*((char*)dst+num) = *((char*)src+num);//num是向后移动的字节数}}return ret;
}

我们先保存目的地的起始地址。然后if判断。
如果src > dst。那就从前往后拷贝。跟memcpy一样。
如果src < dst。那就从后往前拷贝。
我们用while循环拷贝每个字节,src+num找到拷贝的内存字节。

  • 图解


每次循环num–,就是拷贝内存字节前移。

  • 验证

三.memse函数的使用

3.1memset的使用

memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
注意是内存字节而不是元素!

void * memset ( void * ptr, int value, size_t num );

memset函数有三个参数 prt value num。
分别代表 设置内存字节的起始地址 设置字节的值 设置字节的长度。

#include <stdio.h>
#include <string.h>
int main ()
{char str[] = "hello world";memset (str,'x',6);printf(str);return 0;
}

这里我们用memset修改字符串。

那可不可以修改整型呢?

int main()
{int arr[5] = {0};memset(arr, 1, 20);for (int i = 0; i < 5; i++){printf("%d ", arr[i]);}return 0;
}

这里我们想让memset把数组的每个整型改成1。

结果却不是1。这是为什么呢?

  • 未修改前:

  • 修改后:

    因为memset是以字节为单位修改,并不是以元素为单位修改。
    所以memset只会把每个字节改成1。这样输出的数就是0x01010101。转化为10进制就是16843009。
    所以我们在使用memset要特别注意他修改的是字节!


3.2memset的模拟实现

void* my_memset(void* ptr, int value, size_t num)
{void* ret = ptr;for (int i = 0; i < num; i++){*((char*)ptr + i) = value;//修改内存}return ptr;
}

我们先保存起点地址。然后用for循环。
因为是字节修改,所以我们先把指针强制类型转化一下。
然后让指针+i,跳过i个字节指向需要修改的字节。
最后赋值即可。



四.memcmp函数

4.1memcmp函数的使用

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

memcmp有三个参数 ptr1 ptr2 num。

  • 功能
    比较从ptr1和ptr2指针指向的位置开始,向后的num个字节。

  • 返回值

    ptr1字节>ptr2字节,返回大于0的数。
    ptr1字节=ptr2字节,返回等于0的数。
    ptr1字节<ptr2字节,返回小于0的数。


4.2memcmp的模拟实现

int my_memcmp(void* ptr1, void* ptr2, size_t num)
{while (--num &&*((char*)ptr1) == *((char*)ptr2)){ptr1=(char*)ptr1+1;ptr2=(char*)ptr2+1;//移动}//如果相同则一直比较直到不相同//或者移动到最后一个最后一个字节。//出循环后让字节内容作差即可。return *((char*)ptr1) - *((char*)ptr2);
}

我们用while循环判断字节是否相等,
如果相等让字节继续移动。
因为我们只比较num个字节
所以我们循环num-1次,如果前num-1个字节都相等,
那我们就用第num个字节作差。
如果不相等退出,那我们也让他们作差。
这样就实现了memcmp的模拟实现了。

验证:

  • 大于

  • 等于

  • 小于


后言

这就是内存函数的使用和模拟实现啦!小伙伴们可以对内存函数多加使用和熟练掌握。
感谢小伙伴的垂阅,今天就分享到这,咱们下棋见!拜拜~


http://www.ppmy.cn/devtools/23709.html

相关文章

Python学习路线图及开源库和工具推荐

引言 Python作为一门易学易用且功能强大的编程语言&#xff0c;受到了广泛的欢迎和应用。作为一名想要学习Python的初学者&#xff0c;可能有些迷茫&#xff0c;不知道该如何入门&#xff0c;又该如何深入学习。本文将详细介绍Python的学习路线图&#xff0c;同时推荐一些高质…

编译报错 - Missing trailing comma comma-dangle or Missing semicolon semi

一、comma-dangle规则&#xff1a; 这种错误通常出现在使用代码格式检查工具&#xff08;如ESLint&#xff09;时&#xff0c;具体是在JSON或者JavaScript对象、数组的最后一个元素后面缺少了逗号&#xff08;trailing comma&#xff09;。在某些编码标准中&#xff0c;要求在…

srpingMVC基本使用

文章目录 1. springMVC基本功能(1) maven坐标导入(2) 编写表现层(3) springMVC配置类编写(4) 部署tomcat访问 2. 各种请求方法get请求post请求put请求delete请求请求参数提取 3. 请求参数接收(1) param参数接受封装到对象中 (2) 路劲参数接收集合接受时间类型接收json参数接收m…

数字工厂管理系统设备管理功能具有哪些作用

在现代化工业生产中&#xff0c;数字工厂管理系统已成为提升生产效率、优化资源配置、保障生产安全的重要工具。其中&#xff0c;设备管理功能作为数字工厂管理系统的核心组成部分&#xff0c;对于提升设备利用率、降低维护成本、实现智能化生产等方面具有不可或缺的作用。本文…

使用python写一个识别人脸

人脸识别的原理涉及多个领域&#xff0c;包括图像处理、特征提取和机器学习等。以下是一个简化的概述&#xff0c;并展示了如何使用Python和OpenCV库来实现基本的人脸识别。 人脸识别原理概述 图像预处理&#xff1a;首先&#xff0c;我们需要对输入的图像进行预处理&#xf…

webpack前端性能优化- HappyPack多线程打包-打包速度提升n倍

HappyPack 由于运行在 Node.js 之上的 webpack 是单线程模型的&#xff0c;我们需要 webpack 能同一时间处理多个任务&#xff0c;发挥多核 CPU 电脑的威力 HappyPack 插件就能实现多线程打包&#xff0c;它把任务分解给多个子进程去并发的执行&#xff0c;子进程处理完后再把…

大模型评测概述-以司南为例

OpenCompass&#xff08;司南&#xff09;是上海人工智能实验室发布的大模型评测工具。 目前已具有较为完备的生态&#xff0c;集成了大量主流的评测数据集。近期OpenCompass 作为大模型标准测试工具被Meta AI官方推荐。 一、大模型评测的意义 对于普通的使用者&#xff1a;选…

【论文速读】|理解基于大语言模型的模糊测试驱动程序生成

本次分享论文&#xff1a;Understanding Large Language Model Based Fuzz Driver Generation 基本信息 原文作者&#xff1a;Cen Zhang, Mingqiang Bai, Yaowen Zheng, Yeting Li, Xiaofei Xie, Yuekang Li, Wei Ma, Limin Sun, Yang Liu 作者单位&#xff1a;南洋理工大学…